Le timeout MySQL dans l'hébergement survient souvent lorsque les demandes attendent ou que les connexions restent ouvertes trop longtemps. Je te montre comment identifier les causes, régler les timeouts de manière ciblée et ainsi Pannes et Messages d'erreur de réduction.
Points centraux
- Causes: Connexions inactives, requêtes lentes, latence
- Diagnostic: Slow Query Log, EXPLAIN, Logs
- Paramètres: wait_timeout, connect_timeout, pool
- Optimisation: indices, jointures, max_execution_time
- HébergementLimites de connexion, protection DoS
Pourquoi les timeouts de connexion MySQL se produisent dans l'hébergement
Dans les environnements d'hébergement, de nombreuses apps fonctionnent en parallèle, partagent des ressources et génèrent ainsi des coûts supplémentaires. Temps d'attente et Charge de pointe. Les délais d'attente se produisent lorsqu'une connexion reste inactive trop longtemps ou lorsqu'une requête dépasse la limite ; les variables wait_timeout (pour les clients non interactifs) et interactive_timeout (pour les connexions de console) interviennent alors principalement. connect_timeout compte pour l'établissement de la connexion, tandis que net_read_timeout et net_write_timeout sont pertinents pour les processus de lecture et d'écriture. Une seule requête lente sans index approprié peut durer des minutes et engorger le pool de connexion, bloquant ainsi d'autres requêtes. Une latence élevée du réseau ou une grande distance entre le serveur de l'application et la base de données accentue le problème, c'est pourquoi j'évalue toujours les timeouts en même temps que la qualité de la requête et le chemin du réseau.
Classer correctement les messages d'erreur
Je fais d'abord la différence entre „Connection timed out“ (l'établissement échoue) et „Command timeout“ (la commande dure trop longtemps), car les deux sont différents. Causes et Solutions ont été constatés. Des messages tels que „MySQL server has gone away“ indiquent souvent des connexions interrompues, des paquets trop petits (max_allowed_packet) ou un redémarrage brutal. Je reconnais des modèles dans les logs : si les dépassements de temps s'accumulent aux heures de pointe, cela est plutôt dû à la charge ou à un manque de pooling ; s'ils se produisent immédiatement, je vérifie le réseau, le DNS ou les pare-feux. Pour une descente en profondeur structurée, j'utilise le Slow Query Log et j'examine les déclarations critiques avec EXPLAIN. Je résume ici un aperçu compact des causes et des limites : Causes et limites du serveur.
Régler les variables du système de manière ciblée
J'ajuste d'abord les délais d'attente dans la session et je vérifie le comportement avant d'envoyer des messages globaux. Défauts et Fichiers de la session. En fonction de la session, je définis par exemple. SET SESSION wait_timeout = 3600 ;, global par SET GLOBAL wait_timeout = 3600 ;, Les modifications globales sont perdues après un redémarrage. Je saisis les valeurs permanentes dans my.cnf/my.ini, par exemple sous [mysqld] avec wait_timeout, interactive_timeout, connect_timeout, net_read_timeout et net_write_timeout. Ensuite, je redémarre le service et je mesure si les taux d'erreur et les temps de réponse s'améliorent. J'évite les délais d'attente très élevés, car les connexions ouvertes au ralenti mobilisent des ressources et peuvent ensuite déclencher des réactions en chaîne.
Diagnostic : logs, requêtes lentes et temps d'exécution
Pour l'analyse, j'active le Slow Query Log (slow_query_log = 1) et vérifie quelles déclarations passent régulièrement le seuil, car c'est souvent là que se cachent les vrais Freins et Locks. Avec EXPLAIN, je détecte les index manquants, les séquences de jointure défavorables ou Using filesort/temporary, ce qui indique un besoin d'optimisation. Pendant les heures de pointe, je vérifie avec SHOW PROCESSLIST, si des liens sont en attente les uns des autres, et avec SHOW VARIABLES LIKE '%timeout%' (afficher les variables comme '%timeout%')', si les paramètres de session sont différents de ce que je pensais. En PHP, je regarde max_execution_time; Si la valeur est trop petite, le script s'arrête, même si la base de données continue à calculer. Pour une comparaison pertinente, je fais tourner les mêmes requêtes localement contre une copie et je vérifie si la mise en cache, des quantités de données plus petites ou d'autres tampons faussent l'image.
Délimiter proprement les timeouts du serveur web, du proxy et du client
Je sépare strictement les timeouts MySQL des limites web/proxy et client, afin d'éviter de tourner au mauvais endroit. Dans Nginx, contrôler par exemple. proxy_read_timeout, fastcgi_read_timeout et keepalive_timeout les temps d'attente des flux ascendants ; dans Apache, les Délai d'attente et ProxyTimeout pertinent. PHP-FPM termine les requêtes via request_terminate_timeout, même si MySQL continue à calculer. Influencer dans HAProxy timeout client, timeout serveur et timeout tunnel des connexions longues. Côté client, je fixe explicitement des limites de temps pour qu'elles ne soient pas implicitement héritées :
// PHP PDO
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_TIMEOUT => 5, // secondes pour établir la connexion
PDO::ATTR_PERSISTENT => false
]) ;
// mysqli
$mysqli = mysqli_init() ;
$mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5) ; // connect_timeout
$mysqli->options(MYSQLI_OPT_READ_TIMEOUT, 10) ; // net_read_timeout (côté client)
$mysqli->real_connect($host, $user, $pass, $db) ;
// Node.js (mysql2)
const pool = createPool({
host, user, password, database,
connectionLimit : 20, waitForConnections : true, queueLimit : 100,
connectTimeout : 7000, acquireTimeout : 10000, enableKeepAlive : true
}) ;
Important : la somme du timeout du serveur web, de l'app et de la DB ne doit pas donner un „sandwich“ dans lequel la couche externe (par ex. Nginx) s'interrompt plus tôt que les couches internes (app/DB). Je règle les valeurs de manière à ce que les erreurs restent clairement attribuables.
Utiliser le schéma de performance et le schéma sys de manière ciblée
Grâce au schéma de performance et au schéma sys, j'obtiens des informations reproductibles au-delà du journal des requêtes lentes. J'active les instruments pertinents et j'évalue les hotspots par digest :
-- Top statements par 95e centile
SELECT * FROM sys.statements_with_runtimes_in_95th_percentile
ORDER BY avg_timer_wait DESC LIMIT 20 ;
-- Evénements d'attente actifs (locks, I/O, mutex)
SELECT EVENT_NAME, SUM_TIMER_WAIT, COUNT_STAR
FROM performance_schema.events_waits_summary_global_by_event_name
ORDER BY SUM_TIMER_WAIT DESC LIMIT 20 ;
-- Statements „pendants“ actuels
SELECT THREAD_ID, DIGEST_TEXT, TIMER_WAIT, CURRENT_SCHEMA
FROM performance_schema.events_statements_current
WHERE TIMER_WAIT IS NOT NULL ;
Cela me permet de déterminer si les timeouts proviennent plutôt de temps d'attente d'E/S, de chaînes de verrouillage ou de plans gourmands en CPU. Je vérifie en outre sys.user_summary et sys.host_summary, afin de limiter les écarts reconnaissables par compte/hôte. J'évite ainsi de „prolonger“ de manière symptomatique les délais d'attente, alors que le goulot d'étranglement se situe en fait au niveau des verrous ou des entrées/sorties.
Valeurs optimales de timeout selon le scénario
J'adapte les délais d'attente à l'utilisation prévue, car l'interactivité, les durées de travail et l'utilisation de l'ordinateur sont des facteurs importants. Latence et volume de données varient fortement. Les applications web avec de nombreuses requêtes courtes bénéficient de délais d'inactivité plus courts, afin que le pool se nettoie et que les nouveaux utilisateurs obtiennent immédiatement des connexions. Le traitement des données avec des rapports de plusieurs heures nécessite des limites plus généreuses, sinon les tâches importantes se terminent par des timeouts. Pour une latence élevée, j'augmente modérément connect_timeout afin que les temps de connexion n'apparaissent pas à tort comme des erreurs. Le tableau suivant fournit des valeurs de départ stables, que j'ajuste ensuite avec précision à l'aide de valeurs de mesure réelles.
| Réglage | Applications web à fort trafic | Traitement des données | Remarque |
|---|---|---|---|
| wait_timeout | 60 à 300 s | 3600-7200 s | Plus court pour de nombreux utilisateurs, plus long pour les travaux par lots |
| interactive_timeout | 1800 s | 7200 s | Pour CLI/console, rarement critique pour le web |
| connect_timeout | 5-10 s | 10-20 s | Augmenter modérément en cas de latence élevée |
| innodb_lock_wait_timeout | 10-30 s | 50-120 s | Dépend de la durée de la transaction |
Mise en commun des connexions et temps morts
Un pool bien configuré empêche les connexions à vide et garantit que les requêtes sont transmises plus rapidement à une connexion libre. Ressource et Connexion viennent. Je fixe le délai d'inactivité du pool à environ 10-15 % en dessous du MySQL wait_timeout, afin que les sessions se ferment de manière ordonnée avant leur expiration. Le pool limite également les connexions simultanées, ce qui évite les débordements sur les serveurs partagés. Pour WordPress, Nextcloud et d'autres outils similaires, j'observe l'inactivité après les phases de connexion et je configure les connexions en pool de manière à ce qu'elles ne meurent pas trop tôt. J'ai réuni ici plus d'informations de fond et d'exemples pratiques : Pooling de connexions dans l'hébergement.
Faire en sorte que les locks, les deadlocks et les transactions soient courts et concis
De nombreux délais d'attente sont dus à de longues transactions et à des chaînes de verrouillage. Je garde les transactions petites, je lis d'abord les données sans verrouillage et j'ouvre la transaction d'écriture juste avant la mise à jour/l'insertion. En cas de problèmes d'attente, je vérifie innodb_lock_wait_timeout et surtout des deadlocks :
-- Deadlocks et statut InnoDB
SHOW ENGINE INNODB STATUS\G
-- Voir les verrous actifs (MySQL 8+)
SELECT * FROM performance_schema.data_locks\NG
SELECT * FROM performance_schema.data_lock_waits\G
J'évite les schémas peu favorables à l'autocommit (par exemple, les longues sessions ouvertes avec des curseurs „oubliés“). Je m'assure que les schémas d'isolation et d'écriture sont compatibles (par ex. REPEATABLE READ vs. READ COMMITTED) et que les processus secondaires (rapports, exportations) ne conservent pas inutilement de longs verrous. Je résous les deadlocks par la logique Retry dans l'application, mais jamais en augmentant aveuglément les timeouts.
Rendre les requêtes plus rapides : Indices et jointures
J'accélère d'abord les requêtes en utilisant des Indices et plus mince Joins, avant d'augmenter les délais d'attente. Dans EXPLAIN, j'attends une utilisation de l'index pour les filtres et les tris ; si ce n'est pas le cas, je complète la clé de manière ciblée ou je modifie la condition. Pour les grandes tables, je ne stocke pas de larges champs TEXT/BLOB dans le même chemin d'accès s'ils ne sont pas pertinents pour la requête. Je vérifie également si un LEFT JOIN est vraiment nécessaire ou si un INNER JOIN suffit, car cela réduit la quantité de résultats. Grâce à ces étapes, la durée d'exécution diminue sensiblement et le pool reste disponible.
Le tuning PHP, Node et WordPress en pratique
En PHP, pour les longs rapports, j'augmente la max_execution_time modéré et évite les interruptions qui ressemblent à des erreurs de base de données mais qui sont dues au script. se trouvent. Dans la mesure du possible, j'active les reconnexions automatiques dans le pilote ou je traite les erreurs de manière à ce qu'une nouvelle tentative de connexion démarre proprement. Dans Node.js, je gère le keep-live, la taille des pools et les temps d'inactivité à l'aide de mesures réelles de latence et de débit. Sur WordPress, je veille à la mise en cache, aux plugins légers et aux tâches Cron en dehors des heures de pointe. Ainsi, je maintiens la charge de MySQL à un niveau bas et les temps morts restent rares.
Garder un œil sur le chemin du réseau, le DNS et le TLS
Je vérifie le chemin complet entre l'application et la base de données : résolution DNS, routage, pare-feux, NAT et handshakes TLS. Si possible, j'utilise des IP stables ou des DNS internes avec des TTL courts mais pas trop agressifs. Côté serveur, cela empêche skip_name_resolve des reverse-lookups coûteux (attention aux environnements partagés). Avec TLS, je fais attention à la résomption de session et je maintiens le handshake overhead à un niveau bas. TCP-keepalive aide à détecter plus rapidement les connexions mortes ; au niveau du système d'exploitation, les keepalive_time et keepalive_intvl dans l'application, j'active Keep-Alive dans le pilote. Dans les configurations cloud, je tiens compte des délais d'inactivité NAT pour que les connexions pooled ne soient pas „silencieusement“ éliminées alors que l'app les considère encore comme actives.
Limites et nombre de connexions dans l'hébergement
L'hébergement mutualisé limite souvent les connexions simultanées, ce qui rend les demandes difficiles à traiter malgré des délais d'exécution courts. Queues de billard ou Erreur sont en cours d'exécution. Je configure le pool d'applications de manière à ce qu'il respecte ces limites maximales et je détecte les débordements très tôt dans le monitoring. Si les erreurs de 500 augmentent, je vérifie la relation entre max_connections, taille du pool et délais d'attente. Si l'optimisation ne sert pas à grand-chose, je parle avec le fournisseur de limites adaptées ou j'envisage des plans plus importants (vServer, DB dédiée). Tu trouveras ici un guide compact de dépannage : Limites de connexion et erreurs 500.
Choisir un budget de ressources et des max_connections réalistes
Chaque connexion coûte de la RAM : les tampons de tri, de jointure et de lecture s'accumulent par thread. Je prévois donc max_connections non pas en fonction de la demande de pointe, mais de la mémoire disponible. Trop de threads simultanés génèrent des changements de contexte et une pression d'E/S, ce qui tend à favoriser les timeouts. Je considère thread_cache_size et table_open_cache en vue d'éviter que les changements de connexion et de tableau ne coûtent inutilement cher. Grand max_allowed_packet-Les paquets trop volumineux consomment de la RAM et, combinés à de nombreuses connexions, peuvent provoquer des goulots d'étranglement.
Réplication, basculement et mise à l'échelle de la lecture
Dans les configurations répliquées, je vérifie si l'application réagit de manière judicieuse en cas de basculement ou de réplica lag. Pour les charges de lecture, j'utilise des read-replicas, mais je fais attention au retard : un trop petit nombre d'erreurs de lecture ne peut pas être corrigé. net_read_timeout ou App-Timeout peut considérer les longues réponses de réplication comme des erreurs. J'implémente des contrôles de santé et un backoff en cas d'interruption de la connexion au lieu d'une tentative continue agressive. Lors du splitting lecture/écriture, je m'assure que les demandes de lecture cohérentes d'un point de vue transactionnel ne se dirigent pas par erreur vers des répliques retardées - sinon, des „délais d'attente“ apparaissent, qui sont en fait dus à l'attente de données fraîches.
Maintenance, sauvegardes et DDL sans surprises
Les sauvegardes, les DDL en ligne et les index builds peuvent augmenter les I/O et les locks. Je planifie ces travaux en dehors des heures de pointe et j'utilise si possible des algorithmes en ligne. Pendant le DDL, je vérifie innodb_lock_wait_timeout conservateur, afin que les transactions de production ne bloquent pas indéfiniment. Je mesure l'utilisation des E/S pendant les sauvegardes ; si le taux de lecture et le débit du buffer pool entrent en conflit, les temps de réponse augmentent et, en aval, le taux de timeout. Aussi TABLES FLUSH AVEC READ LOCK je ne l'utilise que de manière ciblée, car il peut bloquer globalement.
Indicateurs de suivi et valeurs cibles
Je définis des SLO et les mesure de manière cohérente : latence p95/p99 des requêtes les plus importantes, taux d'erreur par type (Connect vs Command Timeout) et charge de travail. Les métriques importantes sont entre autres. Threads_running (tenir brièvement), Threads_connectés (comparaison de la taille des pools), Aborted_connects et Connection_errors_* (problèmes de réseau/Auth), ainsi que Handler_read_* (utilisation de l'index). Une proportion élevée et constante de „Full Table Scans“ est souvent en corrélation avec les pics de timeout. Je fais en outre afficher par Digest les principaux consommateurs en temps de CPU, d'E/S et d'attente afin d'appliquer les optimisations là où elles font vraiment baisser le taux de timeout.
Timeouts sécurisés vs. risque de DoS
J'équilibre les délais d'attente entre la convivialité et la protection, de sorte que ni Abus toujours interruptions l'emportent sur les autres. En cas de forte latence du réseau, j'augmente prudemment connect_timeout pour éviter que les connexions n'échouent trop tôt. Dans les configurations vulnérables, j'abaisse la même valeur pour que les attaques avec de longs handshake aient moins d'effet. Pour les téléchargements ou les grands ensembles de résultats, j'augmente max_allowed_packet pour que les transmissions ne soient pas interrompues. J'effectue toujours ces interventions en surveillant le taux d'erreur et les temps de réponse afin de voir immédiatement l'effet et les effets secondaires.
Éviter les erreurs fréquentes
Je n'augmente jamais les timeouts à l'aveuglette, car les fenêtres d'attente prolongées sont ouvertes. Réunions et Verrouiller s'accumulent. Au lieu de cela, je corrige d'abord les requêtes lentes, puis j'ajuste les valeurs limites au minimum. Je sépare les longues transactions, fixe des points de contrôle raisonnables et vérifie si innodb_lock_wait_timeout correspond au modèle d'écriture. Si de gros paquets sont nécessaires, je n'augmente max_allowed_packet que dans la mesure du nécessaire et je teste les chemins de téléchargement, d'exportation et d'importation de manière réaliste. Grâce à un monitoring continu, je détecte rapidement les rechutes et maintiens la fiabilité du système.
Résumé : Comment garder des liens fiables
Je commence par un diagnostic clair, je sépare les erreurs de connexion des time-out de commande et je contrôle Logs et Requêtes dans le journal des requêtes lentes. Ensuite, j'optimise les index et les jointures, je place le temps d'inactivité du pool juste en dessous de wait_timeout et je définis des temps de connexion, de lecture et d'écriture réalistes. Pour le trafic web, je choisis des valeurs Idle courtes, pour les jobs batch des limites plus longues ; je teste les deux variantes sous charge. Je coordonne les valeurs limites PHP/Node et les paramètres MySQL pour que l'application et la base de données respirent aussi longtemps l'une que l'autre. Ainsi, les taux d'erreur diminuent, les requêtes restent rapides et le timeout MySQL ne fait plus peur.


