Le client arrive à expiration alors que la requête MySQL continue de fonctionner?

9

Nous avons rencontré un problème dans lequel une requête en lecture seule, exécutée via MySQL Workbench, expirait du point de vue de l'interface utilisateur et restait en cours d'exécution sur le serveur (et apparemment consommait de plus en plus de ressources) jusqu'à ce que nous ayons une panne.

Des questions

  • Existe-t-il un moyen standard de traiter ce type de problème dans MySQL?
  • Y a-t-il une cause fondamentale que nous devons éviter?
asthasr
la source

Réponses:

11

Vous devez examiner les valeurs par défaut en place pour les délais d'expiration:

mysql> show variables like '%timeout';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| connect_timeout            | 10    |
| delayed_insert_timeout     | 300   |
| innodb_lock_wait_timeout   | 50    |
| innodb_rollback_on_timeout | OFF   |
| interactive_timeout        | 60    |
| net_read_timeout           | 30    |
| net_write_timeout          | 60    |
| slave_net_timeout          | 3600  |
| table_lock_wait_timeout    | 50    |
| wait_timeout               | 60    |
+----------------------------+-------+
10 rows in set (0.00 sec)

Habituellement, je surveille plusieurs variables de délai d'expiration. Ceci est très impératif si vous utilisez MySQL à distance depuis MySQL Workbench, client mysql ou application PHP sur un serveur d'application contactant MySQL sur un serveur DB.

Voici ce que dit la documentation MySQL sur ces paramètres:

  • wait_timeout (28800 par défaut [8 heures]): nombre de secondes pendant lesquelles le serveur attend une activité sur une connexion non interactive avant de la fermer. Ce délai d'expiration s'applique uniquement aux connexions de fichiers socket TCP / IP et Unix, pas aux connexions établies à l'aide de canaux nommés ou de mémoire partagée. Au démarrage du thread, la valeur wait_timeout de la session est initialisée à partir de la valeur globale wait_timeout ou de la valeur globale interactive_timeout, selon le type de client (tel que défini par l'option de connexion CLIENT_INTERACTIVE à mysql_real_connect ()). Voir aussi interactive_timeout.
  • interactive_timeout (28800 par défaut [8 heures]): nombre de secondes pendant lesquelles le serveur attend une activité sur une connexion interactive avant de la fermer. Un client interactif est défini comme un client qui utilise l'option CLIENT_INTERACTIVE pour mysql_real_connect (). Voir aussi wait_timeout.
  • net_read_timeout (par défaut 30): Le nombre de secondes pour attendre plus de données d'une connexion avant d'interrompre la lecture. Lorsque le serveur lit à partir du client, net_read_timeout est la valeur de délai d'expiration contrôlant quand abandonner. Lorsque le serveur écrit sur le client, net_write_timeout est la valeur de délai d'expiration contrôlant quand abandonner. Voir aussi slave_net_timeout.
  • net_write_timeout (par défaut 60): Le nombre de secondes pour attendre qu'un bloc soit écrit sur une connexion avant d'interrompre l'écriture. Voir aussi net_read_timeout.

Veuillez vous assurer que ces délais sont suffisamment élevés pour prendre en charge les requêtes qui peuvent s'exécuter pendant une très longue période, notamment:

  • Masse UPDATEs
  • Masse DELETEs
  • ENABLE KEYS sur un grand MyISAM

Pour traiter les requêtes qui continuent de s'exécuter après que vous ayez perdu le contact, vous devez exécuter KILL par rapport à l'ID de processus de la requête longue. Même avec la commande KILL, vous devrez attendre toute requête se trouvant au milieu d'étapes gourmandes en disque ou ayant des mutex internes en cours.

RolandoMySQLDBA
la source
Existe-t-il un moyen standard et robuste d'exécuter KILL sur des processus en cours d'exécution depuis longtemps, ou est-ce généralement fait via un script bash / cron?
asthasr
En fait, j'ai écrit un article en mai 2011 sur la façon de lancer un script en utilisant le schéma
RolandoMySQLDBA
"Veuillez vous assurer que ces délais d'attente sont suffisamment élevés pour prendre en charge les requêtes qui peuvent s'exécuter pendant une très longue période, ce qui peut inclure: MISES À JOUR de masse ..." exemple: php + mysql je dois sélectionner chaque enregistrement dans une colonne de table, alors récupérez puis faites quelque chose ... puis mettez à jour un autre enregistrement avec une nouvelle valeur. Mettez le cas que ce script nécessite environ 5+ minutes. Un SELECT au début et un UPDATE à la fin, récupérer les lignes et faire ... au milieu. Pouvez-vous expliquer ce que doit faire le délai d'attente avec cette situation? Vraiment, ce n'est pas clair pour moi ... quelle est une valeur sûre pour wait_timeout pour libérer la ressource