Vous avez configuré expire_logs_days sur votre serveur MariaDB, mais les fichiers mysql-bin.* continuent de s’accumuler jusqu’à saturer le disque. La purge manuelle échoue avec un warning. Ce guide présente le diagnostic complet et la résolution pas à pas.
Le symptôme
Le disque se remplit progressivement, parfois en moins de 24 heures.
En listant les fichiers dans /var/lib/mysql, on voit beaucoup de fichiers mysql-bin.* :
ls /var/lib/mysql/mysql-bin.[0-9]* | wc -l
134
du -ch /var/lib/mysql/mysql-bin.[0-9]* | tail -1
14M total
Des centaines voire des milliers de fichiers binlog s’accumulent depuis des semaines ou des mois malgré une politique de rétention configurée.
Étape 1 : vérifier la configuration active
Lancer la commande mysql pour avoir le shell de MariaDB :
mysql
puis lancez ces commandes SQL :
SHOW VARIABLES LIKE 'expire_logs_days';
SHOW VARIABLES LIKE 'binlog_format';
SHOW BINARY LOGS;
SHOW MASTER STATUS;
Points à contrôler :
- expire_logs_days à 0 signifie que la purge automatique est désactivée. Suivant la configuration, il faut en garder sur quelques jours, je m’en sers au cas où pour analyser les dernières requêtes. Sinon cela sert pour la réplication mysql. Je mets 3.
- binlog_format = ROW logue chaque ligne modifiée intégralement. C’est beaucoup plus verbeux que STATEMENT ou MIXED et peut multiplier le volume par 10 à 20.
- SHOW BINARY LOGS donne la liste des fichiers avec leur taille.
- SHOW MASTER STATUS indique le fichier binlog actuellement actif.
Étape 2 : identifier ce qui génère le volume
Avant de purger, comprendre la source du volume permet d’éviter que le disque se remplisse à nouveau. Dans la commande suivant, remplacez XXXXXX par un numéro existant.
mariadb-binlog /var/lib/mysql/mysql-bin.XXXXXX \
| grep "^UPDATE\|^INSERT\|^DELETE" \
| sort | uniq -c | sort -rn | head -20
Note : sur les versions récentes de Debian/Ubuntu, la commande s’appelle mariadb-binlog et non mysqlbinlog.
Si elle est absente :
apt install mariadb-client
Si le volume vient d’une application qui écrit massivement dans des tables de logs applicatifs, deux leviers immédiats existent sans toucher à l’application :
- Passer binlog_format de ROW à MIXED dans /etc/mysql/my.conf
- Réduire expire_logs_days à 3 jours si la réplication et la restauration à un instant précis ne sont pas requis
binlog_format = MIXED
expire_logs_days = 3
Étape 3 : tenter la purge manuelle
PURGE BINARY LOGS BEFORE NOW() - INTERVAL 3 DAY;
SHOW WARNINGS;
Si tout se passe bien, les fichiers antérieurs à 3 jours sont supprimés. Mais dans certains cas, MariaDB retourne :
PURGE BINARY LOGS BEFORE NOW() - INTERVAL 3 DAY;
Query OK, 0 rows affected, 1 warning (0.000 sec)
MariaDB [(none)]> SHOW WARNINGS;
+-------+------+-------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-------------------------------------------------------------------------------------+
| Note | 1375 | Binary log 'mysql-bin.003941' is not purged because it is the current active binlog |
+-------+------+-------------------------------------------------------------------------------------+
Et aucun fichier n’est supprimé, même les plus anciens datant de plusieurs mois.
Étape 4 : diagnostiquer le blocage de la purge
Ce message indique que MariaDB considère un vieux fichier comme le binlog actif courant, en contradiction avec SHOW MASTER STATUS qui pointe vers un fichier bien plus récent.
Vérifier l’état de la réplication, qui peut bloquer la purge :
SHOW SLAVE STATUS\G
SHOW SLAVE HOSTS;
Si les deux retournent Empty set, il n’y a pas de réplication. Le blocage vient d’une incohérence interne dans l’état de MariaDB, probablement causée par une interruption brutale passée (crash, coupure électrique, SIGKILL).
Vérifier l’index des binlogs et les fichiers physiques :
# Nombre d'entrées dans l'index interne
wc -l /var/lib/mysql/mysql-bin.index
# Nombre de fichiers physiques réels
ls /var/lib/mysql/mysql-bin.[0-9]* | wc -l
# Premiers et derniers fichiers physiques
ls /var/lib/mysql/mysql-bin.[0-9]* | head -3
ls /var/lib/mysql/mysql-bin.[0-9]* | tail -3
Si le nombre de fichiers physiques est supérieur au nombre d’entrées dans l’index, ou si des fichiers parasites sont présents (extensions inattendues comme .idx), il y a une incohérence entre l’état interne de MariaDB et le système de fichiers.
Un redémarrage de MariaDB peut parfois résoudre l’incohérence :
systemctl restart mariadb
Puis retenter la purge. Si le blocage persiste, passer à l’étape suivante.
Étape 5 : purge manuelle et reconstruction de l'index
C’est la solution de dernier recours quand MariaDB refuse de purger malgré l’absence de réplication et après redémarrage.
Prérequis : s’assurer qu’il n’y a aucune réplication active avant de procéder.
# Arrêter MariaDB
systemctl stop mariadb
# Sauvegarder l'index avant toute modification
cp /var/lib/mysql/mysql-bin.index /var/lib/mysql/mysql-bin.index.bak
# Supprimer les fichiers binlog de plus de 3 jours
# Le pattern [0-9]* capture aussi les fichiers parasites éventuels
find /var/lib/mysql -name "mysql-bin.[0-9]*" -mtime +3 -delete
# Reconstruire l'index avec les fichiers restants
ls /var/lib/mysql/mysql-bin.[0-9]* | grep -v "\.idx$" \
| sed 's|/var/lib/mysql/||' \
| sed 's|^|./|' > /var/lib/mysql/mysql-bin.index
# Redémarrer MariaDB
systemctl start mariadb
Vérifier que MariaDB redémarre correctement et que l’index est cohérent :
systemctl status mariadb
SHOW BINARY LOGS;
SHOW MASTER STATUS;
En résumé
Le problème de binlogs qui saturent le disque malgré expire_logs_days vient le plus souvent de deux causes combinées : un volume d’écritures anormalement élevé (lié au binlog_format = ROW et à une application très active) et une incohérence dans l’état interne de MariaDB qui bloque la purge automatique et manuelle. La résolution passe par une purge physique des fichiers suivie d’une reconstruction de l’index, et par la mise en place d’un monitoring de l’espace occupé par les binlogs.