Les fichiers de log MySQL

Logo

Introduction

MySQL dispose de plusieurs fichiers de log qui permettent de comprendre ce qui se passe dans le process mysqld. La compréhension de ces fichiers de logs est indispensable pour la mise en place de la réplication.

Le log d’erreur Recense tous les problèmes rencontrés au démarrage, à l’exécution et à l’arrêt de mysqld.
Le log isam Recense tous les changements sur les tables ISAM. Utilisé uniquement pour le débogage du code isam.
Le log de requête Recense les connexions établies et les requêtes exécutées
Le log de mise à jour Obsolète : recense toutes les commandes qui modifient les données
Le log binaire (binary log) Recense toutes les commandes qui effectuent des modifications, également utilisées pour la réplication
Le log slow Recense toutes les requêtes dont le temps d’exécution est supérieur au paramètres long_query_time ou bien les requêtes qui n’ont pas pris en compte des index.

Tous les fichiers de log sont généralement dans le répertoire de données data. Il est possible de forcer la main au process mysqld afin de demander la réouverture des fichiers de log (ou dans d’autres cas de basculer vers un nouveau log) en exécutant la commande flush logs (cf la syntaxe FLUSH).

Le log d’erreur

mysqld écrit toutes les erreurs à la sortie standard stderr, erreurs qui sont redirigées par le script safe_mysqld vers un fichier nommé hostname.err (en environnement Windows, mysqld écrit directement vers le fichier \mysql\data\mysql.err).

Ce fichier contient les informations au sujet du démarrage et de l’arrêt de mysqld ainsi que toutes les erreurs critiques trouvées lors de l’exécution de mysqld. Si mysqld est arrêté de manière inattendue, safe_mysqld écrit un ligne sur le redémarrage de mysqld dans ce fichier.

Le log d’erreur comporte également les warnings si mysqld a constaté qu’une table nécessite une vérification ou un réparation.

Sur certains systèmes d’exploitation, le log d’erreur enregistre une 'stack trace' lorsque mysqld s’arrête de façon inopinée.

Exemple : fichier localhost.localdomain.err

020601 16:07:17  mysqld started
/opt/mysql/bin/mysqld: ready for connections
020602  4:38:22  /opt/mysql/bin/mysqld: Normal shutdown
020602  4:38:23  /opt/mysql/bin/mysqld: Shutdown Complete
020602 04:38:23  mysqld ended

Le log de requêtes

Pour avoir connaissance de ce qui se produit avec mysqld, il est possible de démarrer ce dernier avec l’option :

--log[=file]

Cette option permet de recenser toutes les connexions et les requêtes dans un fichier de log (par défaut, ce fichier de log s’appelle hostname.log). Ce fichier de log peut s’avérer très pratique pour détecter les erreurs.

Avec les options –l ou --log, mysqld écrit un fichier de log général avec comme nom de fichier : hostname.log. Le redémarrage ou les rafraîchissements n’engendrent pas la création d’un nouveau fichier (bien que le fichier de log soit fermé puis réouvert). Il suffit simplement d’effectuer une sauvegarde de ce dernier fichier de log.

mv hostname.log hostname-old.log
mysqladmin flush-logs
cp hostname-old.log to-backup-directory
rm hostname-old.log

Le log de mise à jour (update log)

Ce fichier de log est obsolète et remplacé par le log binaire de mise à jour (binary update log)

Lors du démarrage avec l’option -- log-update[=file_name], mysqld écrit un fichier de log contenant toutes les commandes SQL qui mettent à jour des données.

Si aucun nom de fichier n’est donné, ce fichier a pour nomenclature le nom du host. Si un nom de fichier est donné mais qu’en revanche aucun chemin n’est spécifié, le fichier est écrit dans le répertoire data.

Si le nom du fichier ne possède pas d’extension, mysqld créé un fichier de log du style : file_name.###, où ### est un nombre incrémenté lorsque les commandes ci-dessous sont lancées :

  • mysqladmin refresh
  • mysqladmin flush-logs
  • flush logs

ou bien au redémarrage du serveur.

Seules les commandes qui ont effectué effectivement des modifications de données sont inscrites dans ce fichier de log. Ainsi une commande UPDATE ou DELETE avec une clause WHERE qui n’a pas trouvé de lignes ne sera pas transcrite dans le log. Les commandes UPDATE qui appliquent des mises à jour sans modifications sont également écartées.

L’écriture dans le fichier de log est effectuée immédiatement après la fin de l’exécution de la requête mais avant que les verrous soient enlevés et que la validation par la commande commit soit réalisée. Cela permet de s’assurer que le log est fidèle à l’ordre d’exécution.

Pour réaliser la mise à jour d’une base de données à partir de logs d’update, l’opération est la suivante en supposant que les logs d’update sont de la forme file_name.###.

ls –1 –t –r file_name.[0-9]* | xargs cat | mysql

ls permet de récupérer tous les fichiers de logs de mise à jour dans le bon ordonnancement.

Cette opération s’avère très utile lors de la récupération des fichiers de backup après un crash et qu’il est nécessaire de relancer les mises à jour jouées entre le backup et le crash.

Le log binaire de mise à jour (binary log)

Généralités

Le log binaire remplacera à terme le log de mise à jour, aussi le basculement vers ce fichier de log est impératif pour les versions futures de MySQL. Par ailleurs ce fichier est utilisé pour la réplication sous MySQL.

Le log binaire contient toutes les informations du log d’update mais dans un format plus efficace. Ce dernier contient également l’information concernant le temps de mise à jour sur une base de données pour une requête.

Le log binaire est impliqué dans le système de réplication.

Avec l’option --log-bin[=file_name] au démarrage de mysqld, mysqld écrit dans un fichier de log toutes les commandes SQL qui effectuent des mises à jour. Lorsqu’aucun nom de fichier n’est spécifié, ce fichier de log a pour nomenclature le nom du host suffixé par –bin. Si le nom du fichier est donné, mais que le chemin n’est pas spécifié, le fichier est écrit dans le répertoire data.

Si une extension est fournie avec l’option --log-bin=filename.extension, l’extension sera supprimée.

mysqld ajoute une extension numérique au fichier de log binaire qui est incrémentée lorsque les commandes ci-dessous sont lancées :

  • mysqladmin refresh
  • mysqladmin flush-logs
  • flush logs

ou bien au redémarrage du serveur.

Il est également possible de spécifier ce qui doit être écrit dans le fichier de log binaire par mysqld :

binlog-do-db=database_name Permet d’indiquer au master que les mises à jour pour la base de données spécifiée doivent être écrites dans le log binaire, toutes les autres bases non explicitement mentionnées sont exclues.
binlog-ignore-db=database_name Permet d’indiquer au master que les mises à jour pour la base de données spécifiée ne doivent pas être écrites dans le log binaire.

Pour connaître les différents fichiers de log binaires qui ont été utilisés, mysqld créé également un fichier d’index de log binaire qui contient le nom de tous les fichiers binaires de log utilisés. Par défaut ce fichier a le même nom que le fichier de log binaire avec l’extension .index. Il est possible de changer le nom du fichier d’index des logs biaires avec l’option --log-bin-index=[filename]

Si de la réplication est mise en œuvre, il est impératif de ne pas supprimer les anciens fichiers de log binaire avant d’être surs que les esclaves n’auront pas besoin de ces derniers. La meilleure méthode consiste à lancer la commande mysqladmin flush-logs une fois par jour et de supprimer les logs binaires lorsque ces derniers ont plus de trois jours.

Il est possible d’examiner un fichier de log binaire avec la commande mysqlbinlog. A titre d’exemple, il est possible de mettre à jour un serveur MySQL avec la commande ci-dessous :

mysqlbinlog log-file | mysql -h server_name

Il est également possible d’utiliser le programme mysqlbinlog pour lire un log binaire à partir d’un serveur MySQL distant : mysqlbinlog --help permet d’obtenir de plus amples informations.

L’utilisation de BEGIN [WORK] et SET AUTOCOMMIT=0 imposent l’utilisation du log binaire de MySQL pour les backups plutôt que les anciens fichiers de log de mise à jour.

L’écriture dans le fichier de log est effectuée immédiatement après la fin de l’exécution de la requête mais avant que les verrous soient enlevés et que la validation par la commande commit soit réalisée. Cela permet de s’assurer que le log est fidèle à l’ordre d’exécution.

Toutes les mises à jour (update, delete ou insert) qui modifient une table transactionnelle (tables BDB ou InnoDB) sont mises en cache jusqu’à la rencontre de la commande commit. Toutes les mises à jour sur les tables non transactionnelles sont stockées immédiatement dans le log binaire.

Chaque thread alloue au démarrage un buffer dont la taille est spécifiée par le paramètre binlog_cache_size. Si la requête est plus grande que la taille du buffer, le process ouvre un fichier temporaire pour manipuler un cache plus important. Le fichier temporaire est détruit lorsque le thread s’arrête.

Le paramètre max_binlog_cache_size peut être utilisé pour restreindre la taille totale utilisée dans le cache pour une requête multi transactionnelle.

Mise en place

La mise en place des binary logs (pour la future implémentation de la réplication avec MySQL) peut être réalisée en créant le répertoire $MYSQL/logs, puis le sous répertoire $MYSQL/logs/blogs dans lequel seront localisés les fichiers de log binaire.

Le daemon mysql est lancé ensuite comme suit pour la génération des fichiers de log binaires qui auront pour nomenclature blogs.###

./bin/safe_mysqld --log-bin=$MYSQL/logs/blogs/blogs

Dès la première génération d’un fichier de log binaire, le fichier blog.index est créé dans le répertoire $MYSQL/logs/blogs, ce dernier recensant historiquement les fichiers de log binaires de MySQL :

blogs.index
/opt/mysql/logs/blogs/blogs.001

La consultation des fichiers de log binaires est simplement réalisée avec le binaire mysqlbinlog dans le répertoire $MYSQL/bin.

Exemple :

./bin/mysqlbinlog /opt/mysql/logs/blogs/blogs.001 --result-file=/opt/mysql/result.001


Fichier de résultat : result.001
# at 4
#020813  1:21:05 server id  1     Start: binlog v 1, server v 3.23.49a-log created 020813  1:21:05
# at 73
#020813  1:23:41 server id  1     Query  thread_id=2   exec_time=0   error_code=0
use sim_sybase;
SET TIMESTAMP=1029216221;
insert into t_test values (2,"tot");
# at 143
#020813  1:24:13 server id  1     Query  thread_id=2   exec_time=0   error_code=0
SET TIMESTAMP=1029216253;
update t_test
set lib='Essai'
where lib like 'L%';

Le log slow

Généralités

Lors du démarrage de mysqld avec l’option --log-slow-queries[=file_name], mysqld écrit dans un fichier de log toutes les commandes SQL dont le temps d’exécution est supérieur au paramètre long_query_time. Le temps pour l’initialisation des verrous n’est pas pris en compte.

Si aucun nom de fichier n’est donné, le nom par défaut est le nom de la machine hote suffixée avec –slow.log. Si le nom du fichier est donné, mais pas le chemin, ce fichier est écrit dans le répertoire data.

Le log de requête longue est très utile pour traquer les requêtes dont le temps d’exécution est anormal et donc candidates à de l’optimisation. Avec un large log, la tâche peut s’avérer fastidieuse. Il est possible de d’utiliser la commande mysqldumpslow pour obtenir un résumé des requêtes qui apparaissent dans le log.

Avec l’option --log-long-format alors les requêtes qui n’utilisent pas d’index sont enregistrées et listées.

Mise en place

La mise en place des logs slows peut être réalisée en créant le répertoire $MYSQL/logs, puis le sous répertoire $MYSQL/logs/slogs dans lequel seront localisés les fichiers de log slow.

Le daemon mysql est lancé ensuite comme suit pour la génération du fichier de log slow slogs :

./bin/safe_mysqld --log-slow-queries=$MYSQL/logs/slogs/slogs