ERROR 24 (HY000) at line 1: Too many open files (errno: 24). Ce message, remonté cette fois directement par le client MySQL lors d’une requête sur une base volumineuse, ressemble à s’y méprendre à l’incident déjà résolu quelques mois plus tôt sur ce même serveur, où PHP-FPM saturait ses propres descripteurs de fichiers sous forte charge.
Ce billet documente pourquoi la correction déjà appliquée au niveau du système, via le ulimit global, n’a eu aucun effet sur ce nouveau plantage : MySQL gère son propre plafond de descripteurs de fichiers ouverts, indépendamment de la limite système, et ce plafond doit être ajusté séparément.
Le symptôme : un plantage identique en apparence, différent en cause
Le message d’erreur affiché côté client MySQL mentionne le même code d’erreur système, errno 24, que celui déjà rencontré côté PHP-FPM. Cette similitude a d’abord orienté le diagnostic vers une régression du réglage système déjà corrigé : la commande ulimit -n exécutée dans un terminal confirmait pourtant une limite correctement relevée à 65 535 descripteurs pour l’utilisateur système concerné.
Le plantage survenait précisément lors de requêtes touchant un grand nombre de tables simultanément, sur une base WordPress multisite comportant plusieurs centaines de tables distinctes (une conséquence directe de l’architecture multisite, qui duplique un jeu de tables par sous-site).
Diagnostic : MySQL fixe son propre plafond, séparé du système
MySQL dispose d’une variable système dédiée, open_files_limit, qui détermine combien de descripteurs de fichiers le processus mysqld peut ouvrir simultanément, indépendamment de la limite système générale que ulimit configure pour l’ensemble des processus de l’utilisateur.
mysql> SHOW VARIABLES LIKE 'open_files_limit';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| open_files_limit | 1024 |
+------------------+-------+
La valeur affichée, 1024, correspondait à une valeur historique héritée d’une installation ancienne du paquet MySQL sur cette distribution, jamais relevée depuis. Ce plafond, largement suffisant pour une base WordPress classique à quelques dizaines de tables, devenait clairement insuffisant face à une base multisite comptant plusieurs centaines de tables ouvertes simultanément lors de requêtes transversales.

Le correctif : ajuster open_files_limit dans la configuration MySQL
Le correctif consiste à relever explicitement cette variable dans le fichier de configuration de MySQL, généralement /etc/mysql/mysql.conf.d/mysqld.cnf selon la distribution utilisée, avant de redémarrer le service pour que la nouvelle valeur soit prise en compte.
[mysqld]
open_files_limit = 20000
Un point de vigilance mérite d’être signalé : la valeur effectivement appliquée par MySQL au démarrage reste plafonnée par la limite système du processus qui le lance, généralement gérée par le service systemd. Sur les distributions récentes, la directive LimitNOFILE du fichier d’unité systemd du service MySQL doit donc, elle aussi, autoriser une valeur au moins égale à celle demandée dans mysqld.cnf, sans quoi MySQL applique silencieusement une valeur inférieure à celle configurée.
# /etc/systemd/system/mysql.service.d/override.conf
[Service]
LimitNOFILE=24000
Vérification après redémarrage du service
- Relancer
SHOW VARIABLES LIKE 'open_files_limit';après redémarrage et confirmer que la nouvelle valeur est bien appliquée, et non silencieusement plafonnée. - Consulter le journal d’erreurs MySQL au démarrage, qui signale explicitement si la valeur demandée dépasse la limite autorisée par le système, avec la valeur réellement retenue à la place.
- Rejouer, en environnement de test, la requête transversale qui avait initialement déclenché l’erreur, afin de confirmer que le plafond relevé suffit désormais à la charge réelle observée.
Prévention : ne pas confondre les deux plafonds à l’avenir
Cet incident illustre un principe qui dépasse le seul cas de MySQL : sur un serveur exécutant plusieurs services distincts (PHP-FPM, MySQL, serveur web), chaque service peut appliquer son propre plafond de descripteurs de fichiers, en plus de la limite système générale. Corriger l’un ne corrige jamais automatiquement l’autre.
Un même message d’erreur système peut avoir des causes distinctes selon le service qui l’affiche ; vérifier systématiquement si le service concerné dispose de son propre réglage avant de supposer que la limite déjà corrigée ailleurs s’applique de la même façon ici.
En résumé
Le réglage ulimit du système ne suffit pas toujours à éliminer les erreurs de descripteurs de fichiers ouverts : MySQL, via sa variable open_files_limit, maintient son propre plafond, lui-même conditionné par la configuration systemd du service. Corriger l’un sans vérifier l’autre laisse le problème intact, malgré une correction en apparence déjà appliquée au niveau du système.