Comment afficher les requêtes MySQL en direct?

493

Comment puis-je suivre les requêtes MySQL sur mon serveur Linux au fur et à mesure qu'elles se produisent?

Par exemple, j'aimerais configurer une sorte d'écouteur, puis demander une page Web et afficher toutes les requêtes exécutées par le moteur, ou tout simplement afficher toutes les requêtes en cours d'exécution sur un serveur de production. Comment puis-je faire ceci?

barfoon
la source
Selon la gravité d'un problème, je recommanderais fortement d'essayer MySql Proxy. B / c, il peut être placé sur le serveur d'application, a) il est évolutif, b) n'a pas à affecter tout le trafic vers la base de données. Il est en «alpha», mais existe depuis longtemps. dev.mysql.com/downloads/mysql-proxy
Jeff Maass
15
Pourquoi était-ce fermé?! C'est demander comment faire X , pas pour une recommandation. Près de 200 personnes ont trouvé cette question utile. Les mods doivent se calmer.
Cerin
1
J'ai reformulé cette question pour omettre toute référence aux outils. Je pense que cette question est parfaitement sur le sujet ici, car "exécutons-nous les requêtes que nous devrions être?" est une excellente première étape dans le débogage d'un problème lié à la base de données.
Jeffrey Bosboom
1
@MaasSql mysql proxy n'est pas utile pour les développeurs php lors de l'utilisation de PDO car la requête et les valeurs ne sont liées qu'au serveur.
Ananda

Réponses:

300

Vous pouvez exécuter la commande MySQL SHOW FULL PROCESSLIST;pour voir quelles requêtes sont traitées à un moment donné, mais cela n'atteindra probablement pas ce que vous espérez.

La meilleure méthode pour obtenir un historique sans avoir à modifier chaque application utilisant le serveur est probablement par le biais de déclencheurs. Vous pouvez configurer des déclencheurs de sorte que chaque exécution de requête entraîne l'insertion de la requête dans une sorte de table d'historique, puis créer une page distincte pour accéder à ces informations.

N'oubliez pas que cela ralentira probablement considérablement tout sur le serveur, avec l'ajout d'un supplément INSERTau-dessus de chaque requête.


Modifier: une autre alternative est le journal général des requêtes , mais le faire écrire dans un fichier plat supprimerait beaucoup de possibilités de flexibilité d'affichage, en particulier en temps réel. Si vous voulez juste un moyen simple et facile à implémenter pour voir ce qui se passe, activer le GQL puis utiliser l'exécution tail -fsur le fichier journal ferait l'affaire.

Chad Birch
la source
5
Cela peut sembler idiot, mais comment puis-je activer le GQL exactement? J'ai ajouté log_output = file, general_log = 1 et general_log_file = / pathtofile, et j'ai suivi le fichier journal, j'ai visité le site et je n'ai rien obtenu. Qu'est-ce que je fais mal?
barfoon le
Je ne peux être sûr de rien, mais assurez-vous que vous avez redémarré le serveur, et aussi que le fichier que vous avez choisi est celui auquel mysql aurait accès en écriture.
Chad Birch
7
Je l'ai compris - tout ce dont j'avais besoin dans my.cnf était log = / path / to / log Ensuite, j'ai fait la queue à ce sujet et il affiche toutes les requêtes.
barfoon
1
Pour autant que je sache, il n'y a aucun moyen de déclencher quoi que ce soit sur une instruction SELECT. Les déclencheurs s'appliquent uniquement à INSERT, UPDATE, DELETE ... ou suis-je mal informé?
gabe.
1
J'étais au même endroit plus tôt. Actuellement, j'utilise Monyog qui fait tout cela avec très peu de frais généraux, donc rien ne ralentit.
520

Vous pouvez enregistrer chaque requête dans un fichier journal très facilement:

mysql> SHOW VARIABLES LIKE "general_log%";

+------------------+----------------------------+
| Variable_name    | Value                      |
+------------------+----------------------------+
| general_log      | OFF                        |
| general_log_file | /var/run/mysqld/mysqld.log |
+------------------+----------------------------+

mysql> SET GLOBAL general_log = 'ON';

Faites vos requêtes (sur n'importe quel db). Grep ou autrement examiner/var/run/mysqld/mysqld.log

N'oubliez pas de

mysql> SET GLOBAL general_log = 'OFF';

ou les performances chuteront et votre disque se remplira!

artfulrobot
la source
37
Bonne réponse! Vous pouvez utiliser tail -f -n300 /var/run/mysqld/mysqld.logpour garder une trace en direct de votre fichier journal
Claudio Bredfeldt
4
Notez que MySQL 5.1.12 ou supérieur est requis pour ces variables. Avant cela, vous devez redémarrer MySQL pour modifier ces paramètres.
jlh
Existe-t-il un moyen d'obtenir les variables paramétrées écrites dans le journal? Je vois SELECT name FROM person where id=?mais je ne sais pas ce que idc'est.
Jeff
SHOW VARIABLESn'a pas fonctionné pour moi. Fonctionne cependant très SELECT @@GLOBAL.general_log_file;bien. (MariaDB 10.1.9)
phil pirozhkov
1
important - Vous devez vérifier la sortie de journalisation avecSHOW VARIABLES LIKE "log_output%" . S'il est défini sur table, les journaux seront enregistrés dans la base de données elle-même, la table mysql.general_logne se trouvant pas dans le système de fichiers. Vous pouvez le changer file avecSET GLOBAL log_output = 'file';
Arnis Juraga
199

Même si une réponse a déjà été acceptée, je voudrais présenter ce qui pourrait même être l'option la plus simple:

$ mysqladmin -u bob -p -i 1 processlist

Cela imprimera les requêtes en cours sur votre écran chaque seconde.

  • -u L'utilisateur mysql sous lequel vous souhaitez exécuter la commande
  • -p Demander votre mot de passe (vous n'avez donc pas à l'enregistrer dans un fichier ou à faire apparaître la commande dans l'historique de vos commandes)
  • i L'intervalle en secondes.
  • Utilisez l' --verboseindicateur pour afficher la liste complète des processus, affichant l'intégralité de la requête pour chaque processus. (Merci, nmat )

Il y a un inconvénient possible: les requêtes rapides peuvent ne pas apparaître si elles s'exécutent entre l'intervalle que vous avez configuré. IE: Mon intervalle est défini sur une seconde et s'il y a une requête qui prend .02quelques secondes pour s'exécuter et est exécutée entre les intervalles, vous ne la verrez pas.

Utilisez cette option de préférence lorsque vous souhaitez vérifier rapidement les requêtes en cours d'exécution sans avoir à configurer d'écouteur ni rien d'autre.

halfpastfour.am
la source
11
C'est la meilleure solution!
user1398287
3
À mon avis, cette meilleure solution parce que n'utilisez pas une nouvelle connexion mysql pour envoyer la commande à chaque fois, ouvrez plutôt une connexion mysql et utilisez-la pour envoyer la show processlist;
Jose Nobile
@JoseNobile Si vous gardez la connexion mysql ouverte dans votre adaptateur, cela n'a pas vraiment d'importance. Ma solution n'est pas exactement adaptée à OP car ma solution n'est pas prête à être utilisée dans un adaptateur. C'est cependant rapide et facile.
halfpastfour.am
7
Vous pouvez ajouter --verbosepour voir les requêtes complètes
nmat
2
C'est la réponse que je cherchais. Elle devrait être acceptée comme réponse. C'est aussi la réponse la plus simple à mettre en œuvre.
Tchad
51

Exécutez cette requête SQL pratique pour voir l'exécution des requêtes MySQL. Il peut être exécuté à partir de n'importe quel environnement que vous aimez, quand vous le souhaitez, sans aucun changement de code ou surcharge. Il peut nécessiter une configuration des autorisations MySQL, mais pour moi, il fonctionne simplement sans aucune configuration spéciale.

SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND != 'Sleep';

Le seul inconvénient est que vous manquez souvent des requêtes qui s'exécutent très rapidement, il est donc très utile pour les requêtes plus longues ou lorsque le serveur MySQL a des requêtes qui sont en cours de sauvegarde - selon mon expérience, c'est exactement le moment où je veux afficher " requêtes "en direct".

Vous pouvez également ajouter des conditions pour la rendre plus spécifique à n'importe quelle requête SQL.

Par exemple, affiche toutes les requêtes exécutées pendant 5 secondes ou plus:

SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND != 'Sleep' AND TIME >= 5;

Par exemple, afficher toutes les mises à jour en cours d'exécution:

SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND != 'Sleep' AND INFO LIKE '%UPDATE %';

Pour plus de détails, voir: http://dev.mysql.com/doc/refman/5.1/en/processlist-table.html

python1981
la source
17

Je suis dans une situation particulière où je n'ai pas l'autorisation d'activer la connexion et je n'aurais pas l'autorisation de voir les journaux s'ils étaient activés. Je n'ai pas pu ajouter de déclencheur, mais j'avais l'autorisation d'appeler show processlist. Donc, j'ai fait de mon mieux et j'ai trouvé ceci:

Créez un script bash appelé "showsqlprocesslist":

#!/bin/bash

while [ 1 -le 1 ]
do
         mysql --port=**** --protocol=tcp --password=**** --user=**** --host=**** -e "show processlist\G" | grep Info | grep -v processlist | grep -v "Info: NULL";
done

Exécutez le script:

./showsqlprocesslist > showsqlprocesslist.out &

Tail la sortie:

tail -f showsqlprocesslist.out

Bingo bango. Même s'il n'est pas limité, il n'a pris que 2 à 4% de CPU sur les boîtes sur lesquelles je l'ai exécuté. J'espère que cela peut aider quelqu'un.

Michael Krauklis
la source
Ha! Délicieux. Aimer.
Dark Egregious du
Il a besoin d'un certain délai pour éviter une sortie trop verbeuse. Voir mon édition s'il vous plaît.
Slyx
@Slyx merci pour la suggestion de mettre un sommeil dans la boucle. Cependant, si vous recherchez des requêtes de courte durée qui vivent moins longtemps que le sommeil, vous risquez de manquer ce que vous recherchez. Si vous êtes vraiment à la recherche d'un instantané dans le temps, cela ne devrait pas être exécuté en boucle. Il convient également de noter que cela pourrait encore potentiellement manquer des requêtes de très courte durée.
Michael Krauklis
17

strace

Le moyen le plus rapide de voir les requêtes MySQL / MariaDB en direct est d'utiliser le débogueur. Sous Linux, vous pouvez utiliser strace, par exemple:

sudo strace -e trace=read,write -s 2000 -fp $(pgrep -nf mysql) 2>&1

Puisqu'il y a beaucoup de caractères d'échappement, vous pouvez formater la sortie de strace par piping (ajoutez simplement |entre ces deux lignes simples ) ci-dessus dans la commande suivante:

grep --line-buffered -o '".\+[^"]"' | grep --line-buffered -o '[^"]*[^"]' | while read -r line; do printf "%b" $line; done | tr "\r\n" "\275\276" | tr -d "[:cntrl:]" | tr "\275\276" "\r\n"

Vous devriez donc voir des requêtes SQL assez propres sans délai, sans toucher aux fichiers de configuration.

Évidemment, cela ne remplacera pas la manière standard d'activer les journaux, qui est décrite ci-dessous (qui implique de recharger le serveur SQL).

dtrace

Utilisez des sondes MySQL pour afficher les requêtes MySQL en direct sans toucher au serveur. Exemple de script:

#!/usr/sbin/dtrace -q
pid$target::*mysql_parse*:entry /* This probe is fired when the execution enters mysql_parse */
{
     printf("Query: %s\n", copyinstr(arg1));
}

Enregistrez le script ci-dessus dans un fichier (comme watch.d) et exécutez:

pfexec dtrace -s watch.d -p $(pgrep -x mysqld)

En savoir plus: Premiers pas avec DTracing MySQL

Gibbs MySQL Spyglass

Voir cette réponse .

Journaux

Voici les étapes utiles au développement proposé.

Ajoutez ces lignes dans votre ~/.my.cnfou global my.cnf:

[mysqld]
general_log=1
general_log_file=/tmp/mysqld.log

Chemins d'accès: /var/log/mysqld.logou /usr/local/var/log/mysqld.logpeuvent également fonctionner en fonction de vos autorisations de fichier.

puis redémarrez votre MySQL / MariaDB par (préfixez sudosi nécessaire):

killall -HUP mysqld

Vérifiez ensuite vos journaux:

tail -f /tmp/mysqld.log

Après la fin, le changement general_logà 0(vous pouvez l' utiliser à l' avenir), puis retirez à nouveau le fichier et redémarrez le serveur SQL: killall -HUP mysqld.

kenorb
la source
1
Pas besoin de tuer le serveur si vous définissez le à general_logpartir d'une requête MySQL. Il commencera à écrire dans le fichier qui general_log_filepointe.
Robert Brisita
15

C'est la configuration la plus simple sur une machine Linux Ubuntu que j'ai rencontrée. Fou de voir toutes les requêtes en direct.

Recherchez et ouvrez votre fichier de configuration MySQL, généralement /etc/mysql/my.cnf sur Ubuntu. Recherchez la section qui dit «Journalisation et réplication»

#
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
# Be aware that this log type is a performance killer.

log = /var/log/mysql/mysql.log

Décommentez simplement la variable «log» pour activer la journalisation. Redémarrez MySQL avec cette commande:

sudo /etc/init.d/mysql restart

Nous sommes maintenant prêts à commencer à surveiller les requêtes au fur et à mesure qu'elles arrivent. Ouvrez un nouveau terminal et exécutez cette commande pour faire défiler le fichier journal, en ajustant le chemin si nécessaire.

tail -f /var/log/mysql/mysql.log

Exécutez maintenant votre application. Vous verrez les requêtes de base de données commencer à voler dans votre fenêtre de terminal. (assurez-vous que le défilement et l'historique sont activés sur le terminal)

DE http://www.howtogeek.com/howto/database/monitor-all-sql-queries-in-mysql/

Wil
la source
13

À partir d'une ligne de commande, vous pouvez exécuter:

watch --interval=[your-interval-in-seconds] "mysqladmin -u root -p[your-root-pw] processlist | grep [your-db-name]"

Remplacez les valeurs [x] par vos valeurs.

Ou encore mieux:

 mysqladmin -u root -p -i 1 processlist;
recurse
la source
1
Ceci est en fait un très bon extrait qui pourrait être utile .. Merci!
MGP
exactement ce que je cherchais !! la montre doit être installée séparément.
Tilo
12

Découvrez mtop .

Chris KL
la source
1
Oui, mais bonne chance pour l'installer sur Debian ou Ubuntu: bugs.launchpad.net/ubuntu/+source/mtop/+bug/77980
mlissner
Géré pour le faire fonctionner sur Debian, mais son genre de valeur car il manque beaucoup de requêtes. Je peux voir le compteur de requêtes augmenter constamment, mais il n'affiche que rarement des requêtes. Il semble qu'il affiche uniquement les requêtes qui prennent plus de 1 seconde environ.
Cobra_Fast
@Cobra_Fast clairement indiqué sur la page mtop Sourceforge: mtop (MySQL top) monitors a MySQL server showing the queries which are taking the most amount of time to complete. mtop.sourceforge.net C'est parfois très utile.
Ian Lewis
7

J'ai cherché à faire de même, et j'ai concocté une solution à partir de divers articles, et j'ai créé une petite application de console pour sortir le texte de la requête en direct pendant qu'il est écrit dans le fichier journal. C'était important dans mon cas car j'utilise Entity Framework avec MySQL et je dois pouvoir inspecter le SQL généré.

Étapes pour créer le fichier journal (duplication d'autres articles, tous ici pour plus de simplicité):

  1. Modifiez le fichier situé dans:

    C:\Program Files (x86)\MySQL\MySQL Server 5.5\my.ini

    Ajoutez "log = development.log" au bas du fichier. (Notez que l'enregistrement de ce fichier m'a obligé à exécuter mon éditeur de texte en tant qu'administrateur).

  2. Utilisez MySql workbench pour ouvrir une ligne de commande, entrez le mot de passe.

    Exécutez ce qui suit pour activer la journalisation générale qui enregistrera toutes les requêtes exécutées:

    SET GLOBAL general_log = 'ON';
    
    To turn off:
    
    SET GLOBAL general_log = 'OFF';

    Cela entraînera l'écriture des requêtes en cours d'exécution dans un fichier texte à l'emplacement suivant.

    C:\ProgramData\MySQL\MySQL Server 5.5\data\development.log
  3. Créez / exécutez une application console qui produira les informations du journal en temps réel:

    Source disponible pour téléchargement ici

    La source:

    using System;
    using System.Configuration;
    using System.IO;
    using System.Threading;
    
    namespace LiveLogs.ConsoleApp
    {
      class Program
      {
        static void Main(string[] args)
        {
            // Console sizing can cause exceptions if you are using a 
            // small monitor. Change as required.
    
            Console.SetWindowSize(152, 58);
            Console.BufferHeight = 1500;
    
            string filePath = ConfigurationManager.AppSettings["MonitoredTextFilePath"];
    
            Console.Title = string.Format("Live Logs {0}", filePath);
    
            var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
    
            // Move to the end of the stream so we do not read in existing
            // log text, only watch for new text.
    
            fileStream.Position = fileStream.Length;
    
            StreamReader streamReader;
    
            // Commented lines are for duplicating the log output as it's written to 
            // allow verification via a diff that the contents are the same and all 
            // is being output.
    
            // var fsWrite = new FileStream(@"C:\DuplicateFile.txt", FileMode.Create);
            // var sw = new StreamWriter(fsWrite);
    
            int rowNum = 0;
    
            while (true)
            {
                streamReader = new StreamReader(fileStream);
    
                string line;
                string rowStr;
    
                while (streamReader.Peek() != -1)
                {
                    rowNum++;
    
                    line = streamReader.ReadLine();
                    rowStr = rowNum.ToString();
    
                    string output = String.Format("{0} {1}:\t{2}", rowStr.PadLeft(6, '0'), DateTime.Now.ToLongTimeString(), line);
    
                    Console.WriteLine(output);
    
                    // sw.WriteLine(output);
                }
    
                // sw.Flush();
    
                Thread.Sleep(500);
            }
        }
      }
    }
gb2d
la source
1
Cela a l'air vraiment cool et je vais certainement y jeter un œil, c'est génial de le prendre comme projet OSS et de créer un outil de profilage!
Rippo
Je pense que c'est une bonne idée. J'ai mis un repo SVN sur le code google. Probablement le plus petit projet de système d'exploitation jamais créé, mais cela a été très utile jusqu'à présent. Je vais probablement le prolonger, je serais intéressé de voir si quelqu'un d'autre va plus loin. code.google.com/p/livelogs
gb2d
OP en a besoin pour fonctionner sur sa machine Linux. Il semble que votre réponse soit destinée à une machine Windows. Bien que cette réponse reflète la créativité, elle peut ne pas être utile aux autres.
halfpastfour.am
1

En plus des réponses précédentes décrivant comment activer la journalisation générale, j'ai dû modifier une variable supplémentaire dans mon installation vanilla MySql 5.6 avant d'écrire du SQL dans le journal:

SET GLOBAL log_output = 'FILE';

Le paramètre par défaut était «AUCUN».

David B
la source
0

Gibbs MySQL Spyglass

AgilData a récemment lancé Gibbs MySQL Scalability Advisor (un outil libre-service gratuit) qui permet aux utilisateurs de capturer un flux en direct de requêtes à télécharger sur Gibbs. Spyglass (qui est Open Source) surveillera les interactions entre vos serveurs MySQL et les applications clientes. Aucune reconfiguration ou redémarrage du serveur de base de données MySQL n'est nécessaire (client ou application).

GitHub: AgilData / gibbs-mysql-spyglass

Apprendre encore plus: Packet Capture MySQL with Rust

Commande d'installation:

curl -s https://raw.githubusercontent.com/AgilData/gibbs-mysql-spyglass/master/install.sh | bash
kenorb
la source
2
Spyglass semble nécessiter une clé API d'un serveur qui est en panne, et le dernier commit remonte à 3 ans. Je ne sais pas si ce produit est toujours pris en charge / fonctionne.
Dan Tenenbaum