Corriger l'erreur MySQL « Can't connect through socket »
L'erreur de socket a cinq causes réalistes. Comment déterminer en cinq minutes laquelle vous concerne, et pourquoi localhost et 127.0.0.1 ne sont pas la même chose.
Le message apparaît toujours au pire moment : après un redémarrage, après une mise à jour ou quand le disque s'est rempli pendant la nuit. La formulation est presque toujours la même :
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
Deux informations s'y cachent, que beaucoup lisent sans les voir : le chemin et le nombre entre parenthèses. Les deux indiquent assez précisément où vous devez chercher. Cet article passe en revue les cinq causes réalistes (service arrêté, mauvais chemin de socket dans la configuration, application qui attend un autre chemin que celui utilisé par le serveur, problème de permissions, disque plein), présente le diagnostic dans l'ordre qui mène le plus vite au résultat, et explique la différence entre localhost et 127.0.0.1, qui résout à elle seule près de la moitié des cas.
Lire le message d'erreur en détail
Le client a tenté de se connecter via un socket de domaine Unix, donc via un fichier du système de fichiers et non par le réseau. Le chemin entre guillemets est celui qu'attend le client. Le message ne dit rien du chemin que le serveur utilise réellement. C'est précisément là que se niche souvent le problème.
Le nombre à la fin est le code d'erreur du système d'exploitation :
| Code | Signification | Ce que cela veut dire en pratique |
|---|---|---|
| (2) | No such file or directory | Le fichier socket n'existe pas. Le service ne tourne pas, ou le chemin est faux. |
| (13) | Permission denied | Le fichier existe, mais l'utilisateur appelant n'a pas le droit de l'ouvrir. |
| (111) | Connection refused | Le fichier existe, mais personne n'écoute dessus. Résidu classique après un crash. |
Selon le client et la version, la formulation varie. Ces variantes veulent toutes dire la même chose :
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
ERROR 2002 (HY000): Can't connect to local server through socket '/run/mysqld/mysqld.sock' (2)
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
Depuis PHP, la même erreur se présente ainsi, car PHP ne transmet que l'errno brut :
PDOException: SQLSTATE[HY000] [2002] No such file or directory
Warning: mysqli_connect(): (HY000/2002): No such file or directory
Important pour bien distinguer les cas : ERROR 2003 est autre chose. Il y figure une adresse IP et un port au lieu d'un chemin, c'est la voie TCP. Et ERROR 1045 (28000): Access denied for user signifie que la connexion était établie et que seule l'authentification a échoué. Nous lui consacrons un article à part : Corriger l'erreur MySQL « Access denied for user ».
localhost ou 127.0.0.1 : la différence qui explique la moitié des cas
MySQL et MariaDB traitent localhost comme un cas particulier. Si la configuration contient littéralement localhost, la bibliothèque cliente ignore complètement le nom d'hôte et se connecte via le socket Unix. Si elle contient 127.0.0.1, la connexion passe par TCP sur le port 3306. Ce n'est pas un détail, c'est le cœur du problème : une application configurée avec localhost atteint le serveur par un fichier dont elle tire le chemin d'un tout autre endroit que le serveur.
Le test le plus rapide pour savoir si un serveur tourne est donc celui-ci :
mysql --protocol=TCP -h 127.0.0.1 -P 3306 -u root -p
Si vous obtenez une invite de mot de passe ou un Access denied, le service tourne et vous avez un pur problème de socket. Si vous obtenez ERROR 2003 ... (111), le service ne tourne pas ou n'écoute pas en TCP.
Comme solution définitive, le passage à 127.0.0.1 reste toutefois un second choix. Le socket est plus rapide, il contourne la pile réseau et il n'est en principe pas joignable depuis l'extérieur. Surtout : dans la table des utilisateurs, 'app'@'localhost' ne vaut pas automatiquement aussi pour 'app'@'127.0.0.1'. Si vous changez l'hôte dans l'application et que vous récoltez ensuite un Access denied, vous êtes tombé exactement sur cet effet. Et si vous passez à TCP, vérifiez que bind-address n'est pas resté par inadvertance sur 0.0.0.0, avec une base de données soudain exposée sur Internet. Sur ce point, voyez Sécuriser MariaDB et MySQL ainsi que Configurer le pare-feu UFW.
Le diagnostic en cinq minutes
Étape 1 : le service tourne-t-il seulement ?
systemctl status mariadb
systemctl status mysql
Sur Debian et Ubuntu, l'unité s'appelle mariadb.service pour MariaDB (avec mysql.service comme alias) et mysql.service pour MySQL. Sur AlmaLinux, Rocky Linux et RHEL, elle s'appelle mariadb.service ou mysqld.service. La ligne intéressante est Active:. Si elle indique active (running), passez directement à l'étape 2. Si elle indique failed (Result: exit-code) ou inactive (dead), la cause se trouve dans le journal d'erreurs.
Étape 2 : quel chemin de socket le serveur utilise-t-il vraiment ?
Cela se lit dans les fichiers de configuration, sans que le serveur ait besoin de tourner. my_print_defaults évalue la même chaîne de fichiers que le serveur lui-même, y compris tous les includes. Indiquez d'emblée tous les groupes possibles, et la commande fonctionne alors sur n'importe quelle distribution :
my_print_defaults client client-server mysqld mariadbd | grep -i socket
Les quatre noms de groupes ne relèvent pas d'un excès de zèle, ils répondent à trois pièges qui produisent chacun une sortie vide. my_print_defaults client ne renvoie rien du tout sur toutes les distributions testées, parce que dans 50-client.cnf ou /etc/my.cnf.d/client.cnf toutes les options sont commentées. Sur Debian et Ubuntu, le socket figure à la place dans le groupe [client-server] de /etc/mysql/mariadb.cnf et y apparaît sous la forme --socket=/run/mysqld/mysqld.sock. Dans la famille Red Hat, ce groupe n'existe pas : c'est mysqld qui livre la valeur --socket=/var/lib/mysql/mysql.sock. Et depuis MariaDB 11.8, donc depuis Debian 13, le groupe serveur de 50-server.cnf ne s'appelle plus [mysqld] mais [mariadbd]. Qui n'y appelle que my_print_defaults mysqld obtient une sortie vide et croit à tort sa configuration vide.
Autre possibilité, si le serveur tourne et que vous parvenez à vous y connecter :
mysql -e "SHOW VARIABLES LIKE 'socket'"
Et sans la moindre authentification, en demandant directement au noyau quels sockets Unix sont occupés :
ss -lx | grep -i mysql
Si le shell répond ss: command not found, c'est simplement que le paquet manque. Sur Debian et Ubuntu il s'appelle iproute2, sur AlmaLinux, Rocky Linux et Oracle Linux iproute :
apt-get install -y iproute2
dnf install -y iproute
Vous disposez ainsi du chemin que le serveur met réellement à disposition. Comparez-le caractère par caractère avec celui du message d'erreur. /run/mysqld/mysqld.sock et /var/run/mysqld/mysqld.sock désignent la même chose sur les systèmes modernes, car /var/run est un lien symbolique vers /run. /var/lib/mysql/mysql.sock et /tmp/mysql.sock, eux, ne le sont pas.
Étape 3 : le fichier existe-t-il, et à qui appartient-il ?
ls -la /run/mysqld/
ls -la /var/lib/mysql/mysql.sock
On attend un fichier de type s (socket), appartenant à mysql:mysql, avec les droits srwxrwxrwx. Le répertoire au-dessus devrait être drwxr-xr-x mysql mysql. Si le répertoire /run/mysqld manque complètement, c'est que le serveur n'a jamais démarré avec succès, car il est créé au démarrage.
Étape 4 : lire le journal d'erreurs
Ici, les distributions divergent nettement, et c'est là que se cache la raison la plus fréquente pour laquelle les tutoriels trouvés sur le Web n'aident pas. Sur Ubuntu avec MySQL, le serveur écrit dans /var/log/mysql/error.log. Sur Debian avec MariaDB, log_error est commenté par défaut, le répertoire /var/log/mysql/ n'y existe même pas, et tout atterrit dans le journal. Prenez donc la ligne qui correspond à votre combinaison :
| Système et serveur | Commande |
|---|---|
| Debian ou Ubuntu, MariaDB | journalctl -u mariadb --no-pager -n 50 |
| Debian ou Ubuntu, MySQL | tail -n 50 /var/log/mysql/error.log |
| AlmaLinux, Rocky, RHEL, MySQL | tail -n 50 /var/log/mysql/mysqld.log |
| AlmaLinux, Rocky, RHEL, MariaDB | tail -n 50 /var/log/mariadb/mariadb.log |
Un piège mérite ici une attention particulière, parce qu'il ne produit aucune erreur : sur un système Debian avec MariaDB, mysql.service n'est qu'un alias de mariadb.service. systemctl résout l'alias, mais le journal indexe les entrées sous le vrai nom d'unité. journalctl -u mysql y répond par -- No entries -- et un code de sortie 0, alors même que le journal est plein. Qui n'essaie que cette commande croit le journal vide et continue à chercher au mauvais endroit. L'inverse vaut également : sur un système Ubuntu avec MySQL, journalctl -u mariadb répond lui aussi -- No entries --. Si vous n'êtes pas sûr de l'unité concernée, interrogez les deux d'un coup :
journalctl -u 'mysql*' -u 'mariadb*' --no-pager -n 50
Si vous souhaitez un journal permanent, ajoutez sous Debian et Ubuntu un log_error = /var/log/mysql/error.log dans le groupe serveur de /etc/mysql/mariadb.conf.d/50-server.cnf, créez le répertoire avec install -d -o mysql -g mysql /var/log/mysql et redémarrez.
Cause 1 : le service ne tourne pas (et pourquoi)
Le réflexe est de lancer systemctl start mariadb, mais si le service vient tout juste de mourir de lui-même, il retombera en général aussitôt sur la même erreur. Avant cela, un coup d'œil à trois motifs précis dans le journal vaut la peine.
Disque plein
InnoDB refuse de démarrer dès qu'il ne peut plus écrire ses redo logs. Lignes typiques :
[ERROR] InnoDB: Write to file ./ib_logfile0 failed at offset 0, 1048576 bytes should have been written, only 0 were written
[ERROR] InnoDB: Error number 28 means 'No space left on device'
Can't create/write to file (Errcode: 28 "No space left on device")
Vérifiez les deux, l'espace libre et les inodes libres :
df -h
df -i
Un compteur d'inodes saturé alors que le disque paraît libre arrive plus souvent qu'on ne le croit, le plus souvent à cause de millions de petits fichiers de session ou de cache. Ce que vous pouvez supprimer sans risque et ce qu'il faut laisser en place figure dans Disque plein sous Linux : faire le ménage. Ne supprimez surtout rien à la main dans /var/lib/mysql, en particulier aucun fichier ib_logfile pendant une recovery en cours.
L'OOM killer a été plus rapide
Quand le service disparaît en pleine exploitation sans message d'erreur, c'est souvent le noyau qui a frappé :
dmesg -T | grep -i -E "oom|killed process"
journalctl -k | grep -i oom
Une ligne comme Out of memory: Killed process 1234 (mysqld) est sans ambiguïté. L'erreur de socket n'est alors que le symptôme. Les remèdes sont une innodb_buffer_pool_size plus modeste, moins de workers PHP simultanés ou un peu de swap comme tampon, voir Configurer le swap contre les Out-of-Memory.
Fichier socket orphelin après un crash
Si vous voyez dans le journal :
[ERROR] Do you already have another mysqld server running on socket: /run/mysqld/mysqld.sock ?
[ERROR] Aborting
C'est qu'un fichier socket traîne sans qu'aucun processus lui corresponde. Assurez-vous d'abord qu'aucun serveur ne tourne réellement, puis supprimez le fichier :
systemctl stop mariadb
pgrep -a mysqld
rm -f /run/mysqld/mysqld.sock
systemctl start mariadb
Si pgrep affiche encore un processus, ne supprimez pas le fichier. Sinon toutes les applications en cours perdent leur connexion, et le serveur le recrée au prochain démarrage pendant que l'ancien processus continue de vivre.
Cause 2 : le serveur et l'application ne visent pas le même chemin
C'est le cas où tout tourne et où pourtant rien ne fonctionne : ss -lx montre /run/mysqld/mysqld.sock, mais l'application cherche sous /tmp/mysql.sock. Les déclencheurs typiques sont un serveur compilé soi-même, un passage de MySQL à MariaDB, une migration depuis un serveur avec panneau de contrôle vers un système nu, ou une installation PHP issue d'un dépôt tiers avec d'autres valeurs par défaut.
La voie propre consiste à aligner le chemin à exactement trois endroits. Premièrement du côté serveur. Le fichier concerné porte un nom différent pour chaque combinaison : sous Debian et Ubuntu avec MariaDB /etc/mysql/mariadb.conf.d/50-server.cnf, sous Debian et Ubuntu avec MySQL /etc/mysql/mysql.conf.d/mysqld.cnf, sur AlmaLinux, Rocky Linux et Oracle Linux /etc/my.cnf.d/mariadb-server.cnf ou /etc/my.cnf.d/mysql-server.cnf. Un répertoire /etc/mysql/ n'existe pas du tout dans la famille Red Hat, où tout passe par /etc/my.cnf et /etc/my.cnf.d/ :
[mysqld]
socket = /run/mysqld/mysqld.sock
Deuxièmement pour les outils en ligne de commande, dans 50-client.cnf ou dans un fichier dédié :
[client]
socket = /run/mysqld/mysqld.sock
Troisièmement pour PHP. Les trois entrées du php.ini doivent contenir le même chemin, sinon la configuration du serveur ne sert à rien :
mysqli.default_socket = /run/mysqld/mysqld.sock
pdo_mysql.default_socket = /run/mysqld/mysqld.sock
mysql.default_socket = /run/mysqld/mysqld.sock
Quel php.ini s'applique réellement, c'est php --ini qui vous le dit, à condition que le paquet php-cli soit installé, sinon le shell répond seulement php: command not found. La restriction qui suit compte davantage : php --ini nomme le fichier de la ligne de commande, et pour une application web ce n'est presque jamais le coupable. Ce qui fait foi, c'est le fichier FPM, en général /etc/php/8.3/fpm/php.ini, et ce qui y arrive vraiment se voit avec php-fpm8.3 -i | grep -E 'Loaded Configuration|pdo_mysql.default_socket|mysqli.default_socket'. Après la modification, un redémarrage du service FPM est nécessaire, pas seulement un reload du serveur web. Si une application PHP ne rend toujours rien ensuite, l'arrêt suivant est souvent Corriger l'erreur nginx 502 Bad Gateway.
Pour les applications qui ont le chemin codé en dur et auxquelles vous ne pouvez pas toucher, un lien symbolique sert de dernier recours :
ln -s /run/mysqld/mysqld.sock /tmp/mysql.sock
Cela ne survit toutefois à aucun redémarrage, car /tmp est vidé sur beaucoup de systèmes. De façon durable, cela relève d'une règle tmpfiles ou, mieux, de la configuration de l'application.
Cause 3 : les permissions et un /run/mysqld manquant
Si vous obtenez (13) Permission denied, le socket existe mais votre utilisateur n'y accède pas. Le socket lui-même est généralement en 0777, l'accès échoue alors sur le répertoire au-dessus :
chown mysql:mysql /run/mysqld
chmod 755 /run/mysqld
Le deuxième classique : /run est un tmpfs, donc vide après chaque redémarrage. Le sous-répertoire /run/mysqld est recréé au démarrage, soit par systemd-tmpfiles, soit par le script de démarrage. Si la règle correspondante n'a jamais été livrée lors d'une installation manuelle, le serveur démarre exactement une fois (tant que le répertoire créé à la main était là) et plus jamais après le redémarrage suivant. Créez alors /etc/tmpfiles.d/mysql.conf :
d /run/mysqld 0755 mysql mysql -
Cela s'applique sans redémarrage avec systemd-tmpfiles --create. Si vous exploitez votre propre unité, vous pouvez à la place définir RuntimeDirectory=mysqld, voir Créer un service systemd.
Cause 4 : AppArmor et SELinux
Ces deux-là produisent la variante la plus déroutante de l'erreur, car les permissions dans le système de fichiers ont l'air correctes et le serveur signale malgré tout :
[ERROR] Can't start server: Bind on unix socket: Permission denied
[ERROR] Do you already have another mysqld server running on port: 3306 ?
Sur Ubuntu, le paquet MySQL fournit un profil AppArmor. Si vous avez placé le chemin du socket à un endroit inhabituel, le profil interdit la création du fichier. Les refus n'apparaissent pas dans le journal MySQL, mais ici :
dmesg -T | grep -i apparmor
journalctl -k | grep -i denied
Le profil s'étend dans /etc/apparmor.d/local/usr.sbin.mysqld, où l'on ajoute une ligne du type /run/mysqld/mein.sock rw,, suivie de systemctl reload apparmor. Sur AlmaLinux et Rocky Linux, SELinux joue le même rôle : vous y vérifiez avec ausearch -m avc -ts recent et vous positionnez le contexte avec semanage fcontext et restorecon. Dans les deux cas, le plus commode reste de laisser le socket à son emplacement standard.
Les différences entre distributions en un coup d'œil
La plupart des tutoriels affirment qu'il existe un chemin unique pour tous les systèmes. C'est faux, et c'est exactement là que le copier-coller de solutions trouvées ailleurs échoue. État en juillet 2026 :
| Système | Serveur | Socket | Unité | Journal |
|---|---|---|---|---|
| Debian 13 | MariaDB 11.8 | /run/mysqld/mysqld.sock | mariadb | journalctl |
| Debian 12 | MariaDB 10.11 | /run/mysqld/mysqld.sock | mariadb | journalctl |
| Ubuntu 24.04 | MySQL 8.0 ou MariaDB 10.11 | /var/run/mysqld/mysqld.sock | mysql ou mariadb | /var/log/mysql/error.log |
| Ubuntu 22.04 | MySQL 8.0 ou MariaDB 10.6 | /var/run/mysqld/mysqld.sock | mysql ou mariadb | /var/log/mysql/error.log |
| AlmaLinux, Rocky, RHEL | MariaDB ou MySQL | /var/lib/mysql/mysql.sock | mariadb ou mysqld | /var/log/mariadb/mariadb.log |
Deux points en ressortent. Premièrement : Debian ne livre aucun paquet mysql-server, MariaDB y est la référence. Un apt install mysql-server échoue sous Debian, et les tutoriels correspondants trouvés sur le Web ne mènent nulle part. Deuxièmement : dans la famille Red Hat, le socket se trouve dans le répertoire de données et non sous /run. Qui migre une application de Debian vers AlmaLinux en emportant le chemin reproduit l'erreur à coup sûr.
Un cas particulier en marge : dans les conteneurs, il n'y a ni systemd ni le /run/mysqld habituel de l'hôte. Si la base de données tourne dans un conteneur et l'application à côté, il n'existe aucun socket commun. Là, impossible d'éviter TCP et le nom du conteneur comme hôte.
Comment reconnaître que le problème est vraiment réglé
Un systemctl start sans message d'erreur ne prouve rien. Vérifiez dans cet ordre :
systemctl is-active mariadb
ss -lx | grep mysql
mysqladmin ping
mysql -e "SELECT VERSION(), @@socket, @@datadir"
La réponse mysqld is alive de mysqladmin ping est le véritable gage de qualité, car elle passe par le même socket que votre application. Faites ensuite la contre-épreuve depuis la couche applicative, donc pas en tant que root mais avec l'utilisateur sous lequel tourne le serveur web :
sudo -u www-data mysql -u votreutilisateur -p votrebase -e "SELECT 1"
Et pour finir, le test de redémarrage. Une part effrayante des erreurs de socket revient au redémarrage suivant, parce que la réparation n'agissait qu'à l'exécution (répertoire créé à la main, lien symbolique dans /tmp, service non activé). D'où :
systemctl enable mariadb
systemctl is-enabled mariadb
Si possible, redémarrez complètement le serveur une fois et répétez les quatre commandes de contrôle. Sur un serveur root KernelHost, cela prend à peine une minute et vous épargne de revivre l'erreur à trois heures du matin.
Quand la réparation tourne mal
Trois situations dans lesquelles on reste régulièrement bloqué.
Le serveur ne démarre plus du tout après une modification de la configuration. Une faute de frappe dans le .cnf provoque un arrêt immédiat, souvent avec unknown variable. La syntaxe se vérifie sans démarrer le service, mais la commande à utiliser dépend du serveur :
mysqld --validate-config --user=mysql
mariadbd --help --verbose | head -40
La première ligne ne vaut que pour MySQL 8. --validate-config est une option purement MySQL et n'existe dans aucune version de MariaDB, vérifié de la 10.5 à la 11.8. MariaDB répond à la place [ERROR] mysqld: unknown option '--validate-config' suivi de [ERROR] Aborting, et dans la famille Red Hat ce message n'apparaît même pas dans le terminal, uniquement dans le journal d'erreurs : la commande y reste totalement muette. Le --user=mysql est lui aussi obligatoire et non accessoire, car lancé en tant que root, MySQL 8 s'interrompt encore avant avec Please consult the Knowledge Base to find out how to run mysqld as root!. Pour MariaDB, il n'existe pas d'équivalent à --validate-config. La deuxième ligne y montre quelles options le serveur connaît, et my_print_defaults mysqld mariadbd montre ce qu'il lit réellement dans vos fichiers.
Conservez une copie avant chaque modification, le retour en arrière tient alors en un seul cp. Faites également attention au fichier dans lequel vous écrivez : sous Debian et Ubuntu, les fichiers de conf.d sont lus par ordre alphabétique, et une entrée plus tardive écrase une entrée plus ancienne.
Vous n'arrivez plus à entrer en tant que root. Avec MariaDB sous Debian et Ubuntu, l'authentification par unix_socket est préconfigurée pour root@localhost. Autrement dit : sudo mysql fonctionne sans mot de passe, tandis que mysql -u root -p lancé par un utilisateur ordinaire échoue, et ce avec ERROR 1698 (28000): Access denied for user 'root'@'localhost'. Ce n'est pas un problème de socket, c'est un comportement voulu.
Vous avez supprimé le fichier socket pendant que le serveur tournait. Le processus continue de tourner, garde l'inode supprimé et n'est plus joignable par le chemin. Le fichier ne peut pas être recréé à la main, un socket ne naît que du bind() du processus. Seul un redémarrage propre du service aide ici. Tant qu'il n'a pas eu lieu, vous atteignez le serveur en TCP avec --protocol=TCP, pour autant que skip-networking ne soit pas activé. Profitez de cette fenêtre pour faire un dump des bases les plus importantes avant de redémarrer.
Une dernière remarque sur l'ordre des opérations : ne changez jamais plusieurs choses à la fois. D'abord l'état du service, puis la comparaison des chemins, puis les permissions. Qui touche en parallèle au my.cnf, au php.ini et aux droits sur les fichiers ne sait plus ensuite ce qui a aidé, et recommence tout à zéro la fois suivante. Si vous montez un système à neuf et voulez éviter ces pièges dès le départ, la checklist pour un nouveau serveur root vous aidera, et pour la pile base de données complète avec interface web, l'article Installer Apache, PHP, MySQL et phpMyAdmin sur Debian.
Questions fréquentes
Que signifie le nombre entre parenthèses à la fin du message d'erreur ?
Pourquoi 127.0.0.1 fonctionne-t-il alors que localhost ne fonctionne pas ?
Puis-je simplement basculer partout sur 127.0.0.1 ?
Où trouver le journal d'erreurs si /var/log/mysql/error.log n'existe pas ?
Pourquoi le chemin du socket est-il différent sur AlmaLinux et sur Debian ?
Ai-je le droit de supprimer le fichier mysqld.sock ?
Le serveur ne démarre plus jamais après un redémarrage, alors qu'il tournait avant. D'où cela vient-il ?
2026 KernelHost GmbH. Tous droits réservés. Ce guide est protégé par le droit d'auteur. Sa republication sur d'autres sites web, même partielle ou sous une forme modifiée, n'est pas autorisée sans notre accord écrit. Les citations accompagnées de la source et d'un lien sont expressément les bienvenues.

