MySQL vs MariaDB : le choix « par défaut » qui ralentit secrètement votre VPS

Cet article vous a aidé ?

La première fois que vous le remarquez, on dirait un problème réseau. Les pages se bloquent « au hasard », les appels d’API expirent et la charge moyenne du VPS ressemble à une œuvre d’art moderne.
Puis vous regardez de plus près et réalisez que la base de données fait ce que font les bases : transformer silencieusement des péchés de configuration mineurs en latences majeures.

Sur un petit VPS, le « par défaut » n’est pas neutre. Un paramétrage par défaut représente un ensemble d’hypothèses faites pour la machine de quelqu’un d’autre : RAM différente, stockage différent, charge différente, tolérance au risque différente.
Choisir MySQL ou MariaDB parce que le gestionnaire de paquets est plus simple peut vous coûter cher en IOPS, en pression mémoire et en surprises lors de la réplication.

La thèse : les valeurs par défaut nuisent aux petites instances

Sur un VPS, la base de données n’est pas juste un processus parmi d’autres. C’est le processus qui transforme des cycles CPU en attente visible par l’utilisateur.
Si vous avez 1–4 vCPU avec une RAM modeste et un backend de stockage partagé, la différence entre « acceptable » et « insupportable » tient souvent
à un seul paramètre par défaut : dimensionnement du buffer pool, réglages de durabilité, comportement de fsync, ou un thread en arrière-plan qui est adapté à un serveur costaud
mais impitoyable sur une petite machine.

MySQL et MariaDB sont suffisamment proches pour que beaucoup les considèrent comme interchangeables. Mais les internals ont divergé
depuis des années, et les configurations par défaut (surtout dans les builds distribués) peuvent vous mettre dans une situation de lenteur en différé :

  • Taille du buffer pool InnoDB trop petite → lectures constantes, IOPS disque élevés et latence de queue.
  • Vidange trop agressive → pics de profondeur de file de stockage, blocages et timeouts « mystères ».
  • Mauvaises SQL modes ou comportement de l’optimiseur → plans qui semblent corrects jusqu’à ce que la table grossisse.
  • Supposer un « drop-in replacement » pour la réplication ou les outils → migrations pénibles au pire moment.

La bonne façon de choisir est ennuyeuse : décider en fonction de la compatibilité opérationnelle, des performances prévisibles pour votre charge et du chemin de montée de version.
Si vous êtes sur un VPS typique exécutant une application web avec des tables InnoDB, je serai franc : choisissez le moteur que vous pouvez mettre à niveau en toute confiance et configurer correctement,
puis adaptez les valeurs par défaut à votre environnement. L’ennemi n’est ni MySQL ni MariaDB. L’ennemi est de laisser le paquet décider de votre posture de production.

Faits et historique importants en production

Quelques faits concrets et points de contexte qui expliquent pourquoi « ils sont à peu près identiques » a cessé d’être vrai :

  1. MariaDB a été forké de MySQL en 2009 après les inquiétudes autour de l’acquisition d’Oracle de Sun. L’intention était la continuité ; la réalité a été la divergence.
  2. MySQL 8.0 a supprimé le query cache (il était une aimant à mutex globaux). MariaDB a conservé une variante plus longtemps, et de nombreuses distributions incluent encore des configs qui le mentionnent.
  3. MySQL 8.0 utilise un dictionnaire de données transactionnel intégré à InnoDB. MariaDB implémente les métadonnées différemment. Cela affecte le comportement des mises à niveau, la récupération après crash et les outils.
  4. MariaDB a introduit Aria comme remplacement de MyISAM pour les tables temporaires internes et la sécurité en cas de crash. C’est utile parfois, mais c’est un composant supplémentaire.
  5. MySQL a ajouté « instant ADD COLUMN » (dans de nombreux cas) et amélioré le comportement de DDL en ligne ; MariaDB a sa propre histoire d’online DDL et ses cas limites.
  6. Les implémentations GTID diffèrent entre MySQL et MariaDB. Elles partagent l’acronyme, pas une compatibilité totale. Cela compte quand vous devez basculer à 2h du matin.
  7. Les plugins d’authentification par défaut ont divergé (notamment autour de MySQL 8). Vos drivers d’application et clients legacy peuvent en dépendre plus que vous ne le pensez.
  8. Les deux sont optimisés pour le débit, pas pour votre VPS—ce qui signifie que la vidange en arrière-plan et la concurrence de threads peuvent améliorer les benchs tout en rendant la latence très variable sur un stockage contraint.

Une citation reste la meilleure synthèse de pourquoi tout cela importe :
paraphrased ideaWerner Vogels : tout finit par tomber en panne, donc vous concevez et opérez en partant du principe que des pannes auront lieu, pas en espérant qu’elles n’auront pas lieu.

Ce qui ralenti réellement une base sur VPS

« La base de données est lente » n’est pas un diagnostic. Sur un VPS, c’est généralement une ou plusieurs de ces catégories :

1) Latence de stockage et comportement de fsync (le tueur silencieux)

Le stockage VPS est souvent soutenu par le réseau, sur-engagé ou fortement mis en cache. Votre benchmark peut afficher 20k IOPS, mais votre base a besoin
de latence constante, pas de chiffres héroïques en rafale. InnoDB est une machine à durabilité : il écrit des redo, effectue des flush et attend des fsync stables.
Si la latence de fsync augmente, les transactions s’entassent, les threads se bloquent et votre appli commence à accuser « la base de données » comme si c’était un être pensant.

Le pire : votre CPU peut être inactif alors que tout attend le stockage. Vous verrez un faible usage CPU, une charge élevée et une file de threads en « waiting for handler commit ».

2) Pression mémoire : buffer pool trop petit + lutte avec le cache de pages Linux

Sur un petit VPS, vous n’avez pas de RAM à gaspiller. Si votre innodb_buffer_pool est trop petit, vous thrasherez les pages et irez constamment sur disque.
S’il est trop grand, l’OS commence à récupérer de façon agressive, votre machine swappe, et tout devient lent, y compris les logs de la base, parce que le noyau est de mauvaise humeur.

Le buffer pool « correct » n’est pas un mantra comme « mettez-le à 80 % ». Il dépend de ce qui tourne à côté sur la machine, de la taille de votre working set
et de si vous privilégiez une latence stable plutôt que le meilleur taux de cache maximal.

3) Valeurs de concurrence qui ne correspondent pas à votre nombre de vCPU

MySQL et MariaDB peuvent lancer des threads d’arrière-plan et des comportements concurrents qui vont très bien sur 16 cœurs mais sont absurdes sur 2.
Si vous observez de la contention de mutex, beaucoup de context switching ou un overhead d’ordonnancement de threads, le goulot n’est pas le SQL. C’est la chorégraphie des ressources.

4) Plans de requête qui « fonctionnaient hier »

Sur de petits jeux de données, de mauvais index sont masqués par le cache. Sur un VPS, au moment où le dataset cesse de tenir en RAM,
un index composite manquant devient des I/O aléatoires et un slow query log plein de honte.
Les différences d’optimiseur entre MySQL et MariaDB peuvent déterminer quelles requêtes tombent en panne les premières.

Blague n°1 : si vous ne pouvez pas reproduire la lenteur en staging, félicitations — vous avez construit un environnement de staging excellent pour mentir.

Différences pratiques : MySQL 8 vs MariaDB aujourd’hui

Parlons de choix qui changent les résultats sur un VPS, pas de débats idéologiques.

Le packaging et la configuration « par défaut » font la moitié du travail

Sur les familles Debian/Ubuntu, installer mysql-server peut vous donner MariaDB selon la distro et la version.
Sur certaines distributions, MariaDB est livré avec des extraits de configuration qui incluent des réglages legacy ou des valeurs conservatrices.
Les paquets communautaires MySQL ont souvent leurs propres valeurs par défaut qui supposent que vous allez tuner selon votre matériel.

Le schéma dangereux : vous pensez avoir choisi « MySQL », mais en fait vous avez choisi « ce que les mainteneurs de la distro ont testé pour une compatibilité générale ».
Cela peut être correct pour « ça démarre », et faux pour « ça reste rapide ».

Compatibilité de la réplication et des outils opérationnels

Si vous répliquez, le choix a plus d’importance.
MariaDB a des fonctionnalités que MySQL n’a pas, et vice versa. Mais le piège majeur est que les ensembles GTID et les sémantiques ne sont pas interchangeables.
Si vous prévoyez de changer de moteur plus tard, vous vous inscrivez à un projet de migration, pas à une simple mise à jour de paquet.

Pour un VPS mono-nœud, la réplication peut quand même exister (réplicas en lecture, replicas pour migration, DR).
Si vous voulez un replica rapide, « GTID et formats de binlog compatibles » n’est pas un détail mignon.

La performance n’est pas « lequel est plus rapide », c’est « lequel est prévisible »

L’un comme l’autre peut être rapide. Les deux peuvent être lents. La question pratique est : lequel vous donne le comportement le moins surprenant sous contrainte,
avec la sémantique de mise à niveau et de configuration la moins déroutante, sur l’OS que vous utilisez ?

  • Si vous avez besoin des fonctionnalités de MySQL 8 (comportement JSON moderne, changements du dictionnaire de données, compatibilité d’écosystème), choisissez MySQL et tunez-le correctement.
  • Si votre distro considère MariaDB comme la valeur par défaut et que votre stack est déjà compatible, MariaDB convient — auditez simplement les valeurs par défaut et supprimez la cruft legacy.
  • Si vous devez passer d’un service managé à de l’auto-hébergement, la compatibilité MySQL peut réduire la friction. Mais ne supposez rien ; vérifiez avec vos drivers et SQL modes.

Playbook de diagnostic rapide (premier/deuxième/troisième)

Voici ce que vous faites quand le VPS est lent et que vous avez besoin de réponses avant que vos utilisateurs n’écrivent de la poésie dans la boîte support.

Premier : prouvez si vous êtes lié au CPU, à l’I/O ou à la mémoire

  • Vérifiez l’attente stockage et la file de run : iostat, vmstat.
  • Vérifiez la pression mémoire et le swap : free, sar (si disponible).
  • Vérifiez les états des threads MySQL/MariaDB : processlist / performance schema / compteurs d’état.

Deuxième : identifiez le principal wait à l’intérieur de la base

  • Métriques InnoDB : taux de hit du buffer pool, attentes de log, comportement de l’âge des checkpoints.
  • Requêtes lentes : activez le slow query log brièvement si c’est sûr, ou utilisez les logs existants.
  • Verrous : recherchez des transactions en attente de verrous de ligne ou de verrous de métadonnées.

Troisième : décidez si la correction est une requête/index, une config ou le stockage

  • Si l’attente disque est élevée et que le buffer pool est minuscule : commencez par ajuster la mémoire et la vidange.
  • Si le disque va bien mais que les temps de requête grimpent : examinez les plans et les index.
  • Si tout semble « ok » mais que la latence est saccadée : regardez le comportement de fsync, la vidange en arrière-plan et les crédits de rafale chez votre fournisseur.

Tâches pratiques : commandes, sorties, décisions

Ce sont des tâches réelles que vous pouvez exécuter sur un VPS Linux. Chacune inclut la commande, une sortie d’exemple, ce que cela signifie et la décision à prendre.
Exécutez-les comme checklist pendant un incident, ou comme audit de base quand vous héritez d’un serveur qui « a toujours été comme ça ».

Task 1: Confirm what database you’re actually running

cr0x@server:~$ mysql --version
mysql  Ver 15.1 Distrib 10.11.6-MariaDB, for debian-linux-gnu (x86_64) using  EditLine wrapper

Ce que ça signifie : C’est MariaDB 10.11, pas Oracle MySQL. Les gens confondent le client et le serveur, mais cette sortie est généralement un bon indice.

Décision : Arrêtez de dire « MySQL » dans les tickets. Si vous prévoyez des optimisations ou des fonctionnalités spécifiques à MySQL, revérifiez l’origine du paquet serveur et ses capacités.

Task 2: Confirm the server daemon and package source

cr0x@server:~$ systemctl status mariadb --no-pager
● mariadb.service - MariaDB 10.11.6 database server
     Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; preset: enabled)
     Active: active (running) since Mon 2025-12-29 08:12:31 UTC; 2h 14min ago
       Docs: man:mariadbd(8)
             https://mariadb.com/kb/en/library/systemd/
   Main PID: 742 (mariadbd)
     Status: "Taking your SQL requests now..."
      Tasks: 41 (limit: 2275)
     Memory: 1.2G
        CPU: 38min 12.331s

Ce que ça signifie : Le nom du service et le binaire principal identifient le fork. Notez aussi l’utilisation mémoire : sur un petit VPS, 1.2G peut déjà représenter la totalité de la machine.

Décision : Si vous manquez de mémoire, passez immédiatement au dimensionnement du buffer pool et aux réglages de connexion/threads avant de toucher aux micro-optimisations des requêtes.

Task 3: Check RAM, swap, and whether you’re already losing

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:           3.8Gi       3.1Gi       110Mi        62Mi       640Mi       210Mi
Swap:          2.0Gi       1.4Gi       600Mi

Ce que ça signifie : Vous êtes en train de swapper. « available » est minuscule. Le noyau récupère et la DB va se bloquer de façon imprévisible.

Décision : Réduisez l’empreinte mémoire (buffer pool trop grand, trop de connexions, grandes tables temporaires) ou augmentez la RAM. Tuner sans corriger le swap revient à du cosplay de performance.

Task 4: Determine if you’re I/O-bound right now

cr0x@server:~$ iostat -x 1 3
Linux 6.1.0-18-amd64 (server) 	12/29/2025 	_x86_64_	(2 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          12.00    0.00    6.00   28.00    0.50   53.50

Device            r/s     w/s   rkB/s   wkB/s  rrqm/s  wrqm/s  %util  await
vda             110.0   240.0  4200.0  9200.0     0.0     2.0   96.0   18.7

Ce que ça signifie : %util proche de 100 et await ~19ms : le stockage est saturé et lent. C’est ainsi que l’on obtient des timeouts « aléatoires ».

Décision : Réduisez les écritures (réglages de flush, sync du binlog, batch des transactions), augmentez le hit rate du cache ou migrez vers un stockage plus rapide. Vérifiez aussi les limites de rafale du fournisseur.

Task 5: Check whether your filesystem is full or near-full

cr0x@server:~$ df -h /var/lib/mysql
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        50G   46G  2.0G  96% /

Ce que ça signifie : 96 % d’utilisation n’est pas « ok ». InnoDB a besoin d’espace pour les fichiers temporaires, les logs et les opérations internes.

Décision : Libérez de l’espace maintenant (logs, sauvegardes, vieux binlogs) ou augmentez le disque. N’attendez pas le drame adjacent à « disque plein » qui mène à la corruption.

Task 6: Identify the data directory and check doublewrite/redo pressure context

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'datadir'; SHOW VARIABLES LIKE 'innodb_doublewrite'; SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';"
+---------------+---------------------+
| Variable_name | Value               |
+---------------+---------------------+
| datadir       | /var/lib/mysql/     |
+---------------+---------------------+
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| innodb_doublewrite| ON    |
+-------------------+-------+
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1     |
+--------------------------------+-------+

Ce que ça signifie : La durabilité est réglée sur des valeurs les plus sûres. Sur un stockage VPS bon marché, cela peut se traduire par beaucoup d’attentes de fsync.

Décision : Pour des données vraiment critiques, conservez ces valeurs. Pour des systèmes « on peut rejouer depuis une file », envisagez de changer innodb_flush_log_at_trx_commit à 2, mais uniquement après acceptation explicite du risque.

Task 7: Check buffer pool size vs RAM

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
+-------------------------+------------+
| Variable_name           | Value      |
+-------------------------+------------+
| innodb_buffer_pool_size | 134217728  |
+-------------------------+------------+

Ce que ça signifie : Un buffer pool de 128 MiB sur un serveur de 4 GiB est presque sûrement trop petit sauf si le dataset est minuscule.

Décision : Augmentez-le avec précaution (souvent 1–2 GiB sur un VPS 4 GiB, selon les services co-localisés). Surveillez ensuite le swap et le risque d’OOM.

Task 8: Check buffer pool efficiency and reads-from-disk rate

cr0x@server:~$ mysql -e "SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';"
+---------------------------------------+-----------+
| Variable_name                         | Value     |
+---------------------------------------+-----------+
| Innodb_buffer_pool_read_requests      | 982334112 |
| Innodb_buffer_pool_reads              | 18399244  |
+---------------------------------------+-----------+

Ce que ça signifie : Quelques lectures disque sont normales. Mais si Innodb_buffer_pool_reads augmente rapidement pendant les pics, vous manquez de cache ou d’indexation.

Décision : Si les lectures disque corrèlent avec des pointes de latence, augmentez le buffer pool (si la RAM le permet) et/ou corrigez les index. Ne devinez pas : corrélez avec les fenêtres temporelles.

Task 9: See what the server thinks it’s waiting on (quick triage)

cr0x@server:~$ mysql -e "SHOW FULL PROCESSLIST;" | head -n 15
Id	User	Host	db	Command	Time	State	Info
112	app	10.0.1.25:53142	prod	Query	12	Waiting for handler commit	UPDATE orders SET status='paid' WHERE id=?
118	app	10.0.1.25:53159	prod	Query	11	Waiting for handler commit	INSERT INTO payments(order_id, ...) VALUES (...)
121	app	10.0.1.25:53168	prod	Query	9	Waiting for handler commit	UPDATE inventory SET ...
130	app	10.0.1.25:53201	prod	Sleep	55			NULL

Ce que ça signifie : « Waiting for handler commit » pointe souvent vers une pression sur le flush/redolog/fsync (durabilité + latence stockage).

Décision : Concentrez-vous sur le chemin disque/fsync : dimensionnement des redo logs, politique de vidange, performance du stockage, réglages binlog sync.

Task 10: Check slow query log configuration (and enable briefly if needed)

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'slow_query_log'; SHOW VARIABLES LIKE 'slow_query_log_file'; SHOW VARIABLES LIKE 'long_query_time';"
+----------------+-------+
| Variable_name  | Value |
+----------------+-------+
| slow_query_log | OFF   |
+----------------+-------+
+---------------------+--------------------------+
| Variable_name       | Value                    |
+---------------------+--------------------------+
| slow_query_log_file | /var/log/mysql/slow.log  |
+---------------------+--------------------------+
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| long_query_time | 10.000000 |
+-----------------+-------+

Ce que ça signifie : Il est désactivé et long_query_time est élevé. Sur un VPS, une requête de 1–2s peut déjà ruiner la latence en queue.

Décision : Activez-le temporairement avec un seuil plus bas pendant une fenêtre contrôlée, puis désactivez-le ou faites une rotation agressive pour éviter l’overhead I/O.

Task 11: Verify binary logging and sync settings (write amplification audit)

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'log_bin'; SHOW VARIABLES LIKE 'sync_binlog'; SHOW VARIABLES LIKE 'binlog_format';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | ON    |
+---------------+-------+
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sync_binlog   | 1     |
+---------------+-------+
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+

Ce que ça signifie : C’est sûr mais coûteux. sync_binlog=1 ajoute de la pression de fsync. Sur un stockage fragile, cela peut dominer.

Décision : Si vous ne répliquez pas et n’avez pas besoin de restauration à un instant T via les binlogs, envisagez de désactiver log_bin. Si vous en avez besoin, envisagez sync_binlog=100 (compromis de risque) et documentez le périmètre d’impact.

Task 12: Check temporary table behavior (hidden disk usage)

cr0x@server:~$ mysql -e "SHOW GLOBAL STATUS LIKE 'Created_tmp%'; SHOW VARIABLES LIKE 'tmp_table_size'; SHOW VARIABLES LIKE 'max_heap_table_size';"
+-------------------------+---------+
| Variable_name           | Value   |
+-------------------------+---------+
| Created_tmp_disk_tables | 182331  |
| Created_tmp_files       | 44219   |
| Created_tmp_tables      | 903112  |
+-------------------------+---------+
+----------------+----------+
| Variable_name  | Value    |
+----------------+----------+
| tmp_table_size | 16777216 |
+----------------+----------+
+---------------------+----------+
| Variable_name       | Value    |
+---------------------+----------+
| max_heap_table_size | 16777216 |
+---------------------+----------+

Ce que ça signifie : Beaucoup de tables temporaires dégringolent sur disque, et les limites sont petites (16 MiB). Les opérations de tri/groupement vont marteler le stockage.

Décision : Augmentez-les prudemment (ce sont des valeurs potentielles par connexion), et corrigez les requêtes qui créent d’énormes tables temporaires. Sur VPS, les tables temporaires disque sont des champs de mines de latence.

Task 13: Check connection count and whether you’re thread-thrashing

cr0x@server:~$ mysql -e "SHOW GLOBAL STATUS LIKE 'Threads_connected'; SHOW GLOBAL STATUS LIKE 'Threads_running'; SHOW VARIABLES LIKE 'max_connections';"
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_connected | 312   |
+-------------------+-------+
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| Threads_running | 46    |
+-----------------+-------+
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 500   |
+-----------------+-------+

Ce que ça signifie : 312 connexions sur un petit VPS, c’est souvent de l’automutilation. Même si elles sont en sleeping, l’overhead mémoire et la contention s’accumulent.

Décision : Corrigez le pooling au niveau applicatif, réduisez max_connections et dimensionnez le thread cache de façon appropriée. Si vous avez besoin de centaines de connexions, vous avez probablement besoin d’une machine plus grande ou d’une couche proxy.

Task 14: Check InnoDB log configuration (checkpoint pressure vs recovery time)

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'innodb_log_file_size'; SHOW VARIABLES LIKE 'innodb_log_files_in_group';"
+---------------------+----------+
| Variable_name       | Value    |
+---------------------+----------+
| innodb_log_file_size| 50331648 |
+---------------------+----------+
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_log_files_in_group| 2     |
+--------------------------+-------+

Ce que ça signifie : Des redo logs totalisant ~96 MiB sont petits pour des charges d’écriture intenses. Cela peut forcer des checkpoints fréquents et plus de flushs en arrière-plan.

Décision : Augmentez la taille des logs si vous avez beaucoup d’écritures et que le stockage est instable, en équilibrant le temps de récupération. Planifiez correctement ce changement (redémarrage et gestion des fichiers requis).

Task 15: Confirm actual config files in play (stop tuning the wrong file)

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'pid_file'; SHOW VARIABLES LIKE 'log_error';"
+---------------+------------------------+
| Variable_name | Value                  |
+---------------+------------------------+
| pid_file      | /run/mysqld/mysqld.pid |
+---------------+------------------------+
+---------------+--------------------------+
| Variable_name | Value                    |
+---------------+--------------------------+
| log_error     | /var/log/mysql/error.log |
+---------------+--------------------------+

Ce que ça signifie : Vous savez maintenant où chercher les diagnostics de démarrage et pouvez confirmer quelle instance tourne.

Décision : Ouvrez le log d’erreurs et confirmez l’absence d’avertissements sur des variables ignorées (fréquent quand on copie des configs entre MySQL et MariaDB).

Task 16: Inspect error log for ignored settings or crash recovery hints

cr0x@server:~$ sudo tail -n 40 /var/log/mysql/error.log
2025-12-29 08:12:30 0 [Note] mariadbd: ready for connections.
2025-12-29 09:41:02 0 [Warning] 'query_cache_size' is deprecated and will be removed in a future release.
2025-12-29 10:07:11 0 [Warning] Aborted connection 118 to db: 'prod' user: 'app' host: '10.0.1.25' (Got timeout reading communication packets)

Ce que ça signifie : Des knobs dépréciés peuvent encore fonctionner aujourd’hui mais indiquent une dérive de configuration. Les connections abortées peuvent être des timeouts applicatifs ou des blocages serveur.

Décision : Supprimez les réglages dépréciés et traitez les connections abortées comme un symptôme : corrélez avec l’attente stockage et les blocages de requêtes.

Trois micro-histoires d’entreprise (celles qu’on ne poste pas sur Slack)

Mini-histoire 1 : L’incident causé par une mauvaise hypothèse

Une entreprise exploitait un ensemble de petits nœuds VPS régionaux pour des charges sensibles à la latence. L’étage base de données était « MySQL » dans le vocabulaire de tout le monde.
De nouveaux nœuds ont été provisionnés à partir d’une image de distribution, et personne n’a remis cela en question. Pourquoi le ferait-on ? L’application se connectait, les tables existaient, la réplication « fonctionnait ».

Pendant une fenêtre de maintenance, ils ont ajouté un réplica dans une autre région et prévu un exercice rapide de basculement.
L’exercice a échoué d’une manière ennuyeuse mais catastrophique : l’outil basé sur GTID attendait des sémantiques MySQL et a rapporté un état en conflit.
L’ingénieur d’astreinte a essayé de « réparer » avec des commandes correctes pour un moteur et subtilement incorrectes pour l’autre.

Le résultat n’a pas été une perte de données immédiate. C’était pire : un basculement partiel avec une application qui croyait écrire vers le primaire,
tandis qu’un sous-ensemble du trafic atteignait un nœud qui ne répliquait pas proprement. L’incident a duré assez longtemps pour que des incohérences clients apparaissent.

Le postmortem avait une ligne importante : l’hypothèse que « MariaDB est un remplaçant drop-in de MySQL » était considérée comme un fait,
donc personne n’a documenté quel moteur était réellement déployé. Cette hypothèse s’est propagée dans l’automatisation, les seuils de monitoring et les runbooks.

La correction a été terne et efficace : inventorier chaque nœud, standardiser le moteur/la version par environnement, et ajouter une vérification de démarrage dans la pipeline de déploiement
qui affirme le flavor serveur attendu et les variables critiques. Ils ont arrêté de se fier aux impressions et ont commencé à se fier aux faits.

Mini-histoire 2 : L’optimisation qui a échoué

Une autre équipe chassait la latence d’écriture sur une plateforme VPS économique. Ils ont lu sur les knobs de durabilité et décidé de « rapprocher les choses »
en relaxant le comportement de flush au commit. Le changement était petit, les graphiques semblaient meilleurs et l’équipe a célébré discrètement — parce que les célébrations bruyantes attirent le destin.

Deux semaines plus tard, l’hôte a subi un redémarrage imprévu. La base a récupéré, l’appli est revenue, et tout le monde a pensé qu’ils s’en étaient sortis.
Puis la file support a commencé à se remplir de rapports d’updates récents manquants. Pas des volumes énormes, mais suffisants pour être réels.

Le système se comportait techniquement comme configuré : les transactions reconnues aux clients n’étaient pas nécessairement sur un stockage stable au moment de l’accusé de réception.
C’est exactement ce qu’ils avaient demandé. Le problème n’était pas le knob ; le problème était qu’ils avaient changé le contrat de durabilité sans adapter les attentes du produit.

Le rollback a été immédiat. L’« optimisation » à long terme s’est transformée en plan d’ingénierie réel :
garder une durabilité stricte pour les tables cœur, pousser les écritures moins critiques via une file avec idempotence,
et arrêter d’utiliser les knobs de durabilité de la base comme substitut d’architecture.

Mini-histoire 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise

Une équipe SaaS exécutait MariaDB sur des VPS modestes. Rien de fancy. Mais ils avaient une habitude : des exercices de restauration hebdomadaires.
Pas des restaurations théoriques. De vraies restaurations sur un VPS scratch, avec des tests smoke applicatifs et une validation basique par checksum.

Un jour, un développeur a déployé une migration qui a introduit un motif de requête créant d’énormes tables temporaires sur disque.
La base n’a pas « planté ». Elle est devenue de plus en plus lente à mesure que le disque se remplissait. Finalement il a atteint 100 % et le service est tombé.

La réponse immédiate a été chaotique : libérer de l’espace, tuer les pires requêtes, revenir en arrière sur l’appli. Mais quelques tables avaient été partiellement mises à jour
au moment du remplissage et la logique de rollback n’était pas propre. Ils ont dû restaurer à un point avant la migration.

La pratique des exercices de restauration a payé. L’équipe connaissait déjà les étapes de restauration, l’enveloppe de temps de restauration, et le fichier de configuration
qui était toujours oublié. Ils ont restauré, validé, rejoué uniquement le sous-ensemble sûr des changements, et sont revenus en ligne avec un drame minimal.

L’action finale n’était pas « soyez plus prudents ». Elle était concrète : ajouter des vérifications de plan de requête pour le chemin de migration, surveiller les taux de spill de tables temporaires,
et continuer à faire ces ennuyeux exercices de restauration jusqu’à ce qu’ils vous sauvent le week-end.

Erreurs courantes : symptôme → cause racine → correction

1) Symptom: low CPU, high load average, random timeouts

Cause racine : attente I/O et saturation du stockage ; threads bloqués sur fsync/flush ou lectures lentes.

Correction : Utilisez iostat -x pour confirmer await/%util élevés. Augmentez le buffer pool si sous-dimensionné, réduisez la write amplification (sync du binlog, politique de flush) et envisagez un stockage plus performant.

2) Symptom: performance tanks after “small” traffic increase

Cause racine : le working set ne tient plus dans le buffer pool ; vous effectuez désormais des lectures aléatoires disque.

Correction : Mesurez les lectures buffer pool vs requêtes. Ajoutez les index manquants, augmentez le buffer pool et vérifiez que vous ne swappez pas ensuite.

3) Symptom: sudden stalls during heavy write bursts

Cause racine : pression de checkpoint (redo logs trop petits) ou flush agressif interagissant avec un stockage lent.

Correction : Augmentez la capacité des redo logs si approprié, et ajustez le comportement de vidange. Validez avec des états de processlist comme « Waiting for handler commit ».

4) Symptom: memory usage grows until the box swaps

Cause racine : trop de connexions, gros buffers par connexion, croissance des tables temporaires ou buffer pool fixé trop haut pour la machine.

Correction : Limitez les connexions, mettez en place du pooling, réduisez les buffers par connexion et redimensionnez le buffer pool. Vérifiez avec free -h et Threads_connected.

5) Symptom: replication/failover tooling behaves strangely

Cause racine : supposer que les sémantiques GTID/réplication MySQL et MariaDB correspondent ; versions/flavors mixtes.

Correction : Standardisez le moteur à travers la topologie ou utilisez des plans de compatibilité explicites. Ne mélangez pas sans runbook testé.

6) Symptom: “It got slower after we upgraded”

Cause racine : comportement de l’optimiseur changé, SQL modes ou variables de config non valides ; possible régression due à des valeurs par défaut différentes.

Correction : Faites un diff des variables clés avant/après la mise à niveau, inspectez le log d’erreurs pour des variables ignorées, et re-baselinez avec des échantillons de slow query et des plans EXPLAIN.

Blague n°2 : la base ne devient pas « lente au hasard ». Elle exprime simplement ses sentiments sur vos valeurs par défaut.

Listes de contrôle / plan pas à pas

Plan A: Vous avez un VPS lent maintenant

  1. Stabilisez : confirmez l’espace disque (df -h), arrêtez les requêtes incontrôlées, et assurez-vous que vous ne swappez pas fortement.
  2. Classifiez : lancez iostat -x et free -h. Décidez : I/O-bound vs memory-bound vs CPU-bound.
  3. Top waits : processlist pour les attentes de commit/verrous ; échantillonnage rapide du slow log si sûr.
  4. Réglages rapides : corrigez le buffer pool s’il est minuscule ; réduisez les connexions ; traitez les spills de tables temporaires.
  5. Knobs à risque : ne changez les réglages de durabilité qu’avec accord explicite et étapes de rollback.
  6. Validez : mesurez la latence p95 et l’attente stockage après les changements, pas seulement le QPS moyen.

Plan B: Vous choisissez entre MySQL et MariaDB pour un nouveau VPS

  1. Décidez selon l’écosystème : drivers clients, particularités des ORM, alignement avec les services managés, besoins en réplication.
  2. Choisissez un moteur par environnement : ne mélangez pas « parce que ça a marché une fois ».
  3. Configs de référence : définissez buffer pool, tailles de logs, limites de connexions et politique du slow log de façon intentionnelle.
  4. Planifiez les upgrades : testez les upgrades mineurs et la validité des configs en staging qui reflète au mieux les caractéristiques de stockage du VPS.
  5. Construisez l’observabilité : capturez les slow query logs (avec rotation), métriques OS de base et compteurs d’état DB.

Plan C: Vous exécutez déjà un moteur et voulez basculer

  1. Ne traitez pas ça comme un swap de paquet : traitez-le comme une migration avec tests de compatibilité.
  2. Inventoriez les fonctionnalités : SQL modes, plugins d’authentification, format de réplication, routines stockées, triggers, et comportements charset/collation.
  3. Dry run restore/migrate : pratiquez export/import ou approches de réplication logique sur un nœud scratch.
  4. Coupez avec rollback : définissez des critères de rollback précis (taux d’erreur, lag de réplication, contrôles d’intégrité) et gardez l’ancien primaire en lecture-seule pendant une fenêtre.

FAQ

1) MariaDB est-il plus rapide que MySQL sur un VPS ?

Parfois, selon des charges et versions spécifiques. Mais sur VPS, le déterminant principal est que vos valeurs par défaut correspondent à votre RAM et à la latence du stockage.
Chaque moteur peut être rapide ; chaque moteur peut être catastrophiquement lent.

2) Pourquoi une « installation par défaut » semble souvent lente sur de petits serveurs ?

Les valeurs par défaut visent une large compatibilité et la durabilité. Sur un stockage contraint, un comportement fsync sûr et des caches petits se traduisent par des blocages fréquents.
Il faut redimensionner la mémoire et réduire la write amplification.

3) Puis-je régler le problème en tunant le VPS malgré un stockage lent ?

Vous pouvez réduire les dégâts (plus grand buffer pool, moins de fsync, moins de tables temporaires disque). Mais vous ne pouvez pas tuner la latence de stockage terrible.
Si iostat montre un await élevé sous une charge modeste, changer de stockage ou de fournisseur est probablement la vraie solution.

4) Dois-je changer innodb_flush_log_at_trx_commit à 2 ?

Seulement si vous comprenez et acceptez le compromis de durabilité : vous pouvez perdre jusqu’à environ une seconde de transactions en cas de crash.
Pour beaucoup d’applis web avec queues et idempotence, c’est acceptable. Pour les systèmes financiers ou d’état officiel, généralement non.

5) Désactiver le binary logging est-ce sûr ?

Si vous ne répliquez pas et n’utilisez pas les binlogs pour la restauration à un instant T, désactiver peut réduire la charge d’écriture.
Si vous avez besoin de PITR ou de replicas, gardez-le activé et tunez sync_binlog avec des risques documentés.

6) Pourquoi y a-t-il autant de connexions « Sleeping » dans le processlist ?

C’est typiquement du pooling applicatif ou des connexions fuitées. Sleeping n’est pas gratuit : la mémoire et la gestion des threads coûtent.
Corrigez le pooling et limitez max_connections pour imposer de la discipline.

7) Puis-je mélanger primaire MySQL avec réplicas MariaDB (ou inverse) ?

Parfois dans des configurations limitées, mais c’est fragile et dépendant des versions. En production, partez du principe « non » à moins d’avoir un plan de compatibilité testé, documenté et validé en continu. Ce n’est pas l’endroit pour des surprises.

8) Quel est le meilleur réglage unique pour les performances sur VPS ?

innodb_buffer_pool_size correctement dimensionné pour votre RAM et votre charge, combiné à empêcher la machine de swapper.
Ensuite, le meilleur réglage est généralement « ajoutez le bon index ».

9) Comment savoir si mon problème vient des requêtes ou de la configuration ?

Si iostat montre un await élevé et que les lectures InnoDB grimpent pendant les pics, vous êtes probablement lié au cache/index.
Si le processlist montre des attentes de commit et que le binlog sync est strict, vous êtes probablement lié à la fsync/write-amplification.

10) Dois-je utiliser MyISAM/Aria pour la vitesse sur un VPS ?

Pour les tables applicatives : presque jamais. InnoDB offre la sécurité en cas de crash et un comportement de concurrence adapté.
Changer d’engine pour « la vitesse » déplace généralement la douleur vers la récupération et l’intégrité des données.

Prochaines étapes réalisables cette semaine

Si votre base sur VPS est lente, ne commencez pas par la religion du moteur. Commencez par la mesure, puis supprimez les fautes évidentes auto-infligées.

  1. Identifiez le moteur et la version que vous exécutez réellement et documentez-le dans votre runbook.
  2. Établissez une base OS : capturez free -h, df -h et iostat -x pendant les périodes normales et de pointe.
  3. Redimensionnez l’InnoDB buffer pool et limitez le nombre de connexions pour arrêter de vous battre avec le noyau.
  4. Auditez la write amplification (binlog, réglages sync, flush commit) et décidez explicitement votre contrat de durabilité.
  5. Activez brièvement le slow query logging (avec rotation) et corrigez les principaux coupables avec des index et des modifications de requête.
  6. Exercez une restauration sur un VPS scratch. Pas parce que c’est amusant. Parce qu’un jour ce sera nécessaire et vous aurez besoin de réflexes.

Choisissez MySQL ou MariaDB selon la compatibilité et votre chemin de montée de version. Ensuite, appropriez-vous les valeurs par défaut.
Votre VPS cessera de ralentir « au hasard ». Il deviendra prévisiblement rapide, et c’est le seul type de rapidité qui compte en production.

← Précédent
Proxmox « pmxcfs n’est pas monté » : pourquoi /etc/pve est vide et comment récupérer
Suivant →
Ubuntu 24.04 : NVMe disparaît sous charge — paramètres d’alimentation/ASPM qui le résolvent souvent

Laisser un commentaire