Administration de bases de données : MariaDB, MySQL et PostgreSQL en production
Quitter

Leçon 1 sur 12 · Installer et configurer

MariaDB et MySQL en production : installation, fichiers et my.cnf

55 min Debian 13 Versions MariaDB 10.11, MariaDB 11.4, MariaDB 11.8, MySQL 8.4

Objectif

Installer un serveur MariaDB ou MySQL comme on le fait en production : la bonne version, le bon dépôt, des réglages dans vos propres fichiers, un système préparé pour une base de données, et la certitude de savoir quelle valeur le serveur a vraiment retenue.

L'essentiel

  • Une base de production, c'est un cycle de vie : on choisit une version LTS (support long) et on suit ses versions mineures de correctifs.
  • Les fichiers à connaître : le datadir (/var/lib/mysql), le socket (/run/mysqld/mysqld.sock), le journal d'erreurs, les fichiers my.cnf.
  • my.cnf est lu dans un ordre précis, avec des inclusions ; pour une option répétée, la dernière valeur gagne.
  • On ne modifie jamais les fichiers du paquet : on ajoute son fichier (90-production.cnf) et on vérifie la valeur effective.
  • Le serveur se règle aussi autour de la base : limites systemd, swap, volume dédié monté en noatime.

1. Le métier : ce que le DBA ajoute au « apt install »

Les cours Debian, Red Hat et Ubuntu vous ont montré comment installer MariaDB, créer une base et un compte. Ici, on prend la place de la personne qui répond de la base : elle doit tenir des années, encaisser la charge de la boutique MasterLinux le soir des soldes, être sauvegardée, répliquée, surveillée et mise à jour sans perte.

Questions à se poser avant d'installer :

Question Pourquoi
Quelle version, jusqu'à quand supportée ? MariaDB publie des versions LTS (10.11, 11.4, 11.8…) maintenues environ 5 ans ; MySQL a ses LTS 8.4 et des versions « Innovation » de courte durée.
Paquet de la distribution ou dépôt officiel ? Debian 13 fournit MariaDB 11.8 ; le dépôt de MariaDB ou de MySQL donne une version précise et des mises à jour plus rapides. On choisit une source et on s'y tient.
Moteur de stockage ? InnoDB pour tout (transactions, reprise après panne). MyISAM n'a pas sa place en production.
Quelle machine ? RAM (le cache InnoDB), disques SSD/NVMe, volume dédié pour les données.

2. Installer et repérer les fichiers

apt install mariadb-server mariadb-backup        # Debian / Ubuntu
dnf install mariadb-server mariadb-backup        # Rocky / Alma (MySQL : dnf install mysql-server)

systemctl enable --now mariadb
mariadb -e "SELECT VERSION(), @@datadir, @@socket, @@log_error;"
Élément Debian / Ubuntu Rocky / Alma
Fichier principal /etc/mysql/my.cnf → mariadb.cnf /etc/my.cnf
Dossiers inclus /etc/mysql/conf.d/, /etc/mysql/mariadb.conf.d/ /etc/my.cnf.d/
Données (datadir) /var/lib/mysql /var/lib/mysql
Journal d'erreurs journal systemd (journalctl -u mariadb) ou /var/log/mysql/error.log /var/log/mariadb/mariadb.log
Nom du service mariadb (alias mysql) mariadb ou mysqld

Les commandes ont été renommées : mariadb (client), mariadb-dump, mariadb-admin, mariadb-backup, mariadb-binlog. Les anciens noms mysql* existent encore comme liens sur beaucoup de systèmes, mais disparaissent peu à peu.

3. Comment my.cnf est lu

Sur Debian, /etc/mysql/mariadb.cnf ressemble à ceci :

[client-server]
socket = /run/mysqld/mysqld.sock

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mariadb.conf.d/

Trois règles à graver :

  1. Les sections (groupes) disent qui lit l'option : [mysqld], [server], [mariadb], [mariadb-11.8] (seulement cette version) pour le serveur ; [client], [mysql], [mariadb-dump] pour les outils.
  2. !includedir lit les fichiers du dossier par ordre alphabétique, et seulement ceux qui finissent par .cnf.
  3. Pour une option répétée, la dernière lue l'emporte. Un 99-vieux.cnf oublié bat votre 90-production.cnf.

Pour savoir ce que le serveur va lire, sans le redémarrer :

my_print_defaults --mysqld          # toutes les options du serveur, dans l'ordre de lecture
mariadbd --print-defaults           # même chose, vu par le binaire du serveur
mariadb -e "SELECT @@innodb_buffer_pool_size/1024/1024/1024 AS go, @@max_connections;"   # valeur EN COURS

Dans le lab, la commande cnf-effectif <option> donne la valeur finale qu'aurait le serveur au démarrage (l'équivalent de SELECT @@option).

Variables dynamiques et statiques

Une partie des réglages se change à chaud :

SET GLOBAL max_connections = 300;            -- immédiat, mais perdu au redémarrage
SET GLOBAL innodb_buffer_pool_size = 10*1024*1024*1024;   -- redimensionnement en ligne (InnoDB)

D'autres exigent un redémarrage (innodb_log_file_size sur les anciennes versions, bind_address…). Règle d'exploitation : tout changement à chaud est aussi écrit dans le fichier, sinon il disparaît au prochain redémarrage. MySQL 8 propose SET PERSIST, qui écrit dans mysqld-auto.cnf du datadir ; c'est pratique, mais ce fichier doit être connu de toute l'équipe, sinon personne ne comprend d'où vient une valeur.

4. Les réglages qui comptent pour un serveur dédié

# /etc/mysql/mariadb.conf.d/90-production.cnf — ml-db-01, 16 Go de RAM, dédié
[mysqld]
bind_address                   = 10.10.20.11   # l'adresse du réseau privé, jamais 0.0.0.0 sans pare-feu
skip_name_resolve              = ON            # pas de DNS inverse à chaque connexion (comptes par IP)
max_connections                = 300

innodb_buffer_pool_size        = 10G           # 60 à 70 % de la RAM d'un serveur DÉDIÉ
innodb_log_file_size           = 2G            # journal redo : assez grand pour lisser les écritures
innodb_flush_log_at_trx_commit = 1             # 1 = aucune transaction validée perdue en cas de panne
innodb_file_per_table          = ON            # un fichier par table (défaut)
  • Buffer pool : le cache des pages InnoDB. Trop petit, tout part sur le disque ; trop grand, le serveur swappe ou est tué par l'OOM killer. On laisse de la RAM au système, aux connexions (chacune consomme des tampons) et au cache de fichiers.
  • innodb_flush_log_at_trx_commit : 1 est le seul réglage qui garantit la durabilité. 2 ou 0 vont plus vite mais peuvent perdre la dernière seconde de transactions en cas de coupure : à réserver à une base qu'on peut reconstruire.
  • Jeu de caractères : utf8mb4 partout (l'ancien utf8 de MySQL ne stocke que 3 octets et casse les emojis et certains caractères).

5. Préparer le système

# /etc/systemd/system/mariadb.service.d/limites.conf
[Service]
LimitNOFILE=65535        # une table = des fichiers ouverts ; 1 024 par défaut ne suffit pas
TimeoutStopSec=900       # laisser le temps de vider un gros buffer pool à l'arrêt
systemctl daemon-reload && systemctl restart mariadb
cat /proc/$(pidof mariadbd)/limits | grep 'open files'

Si systemd tue le serveur au bout de 90 secondes pendant l'arrêt, la base redémarre en récupération après panne (crash recovery) : plus long, et inquiétant un soir de maintenance.

echo 'vm.swappiness = 1' > /etc/sysctl.d/60-mariadb.conf && sysctl --system   # swap en dernier recours

Le datadir sur un volume dédié (LVM) : la base ne remplit pas /, on agrandit le volume sans toucher au système, on peut prendre un instantané. noatime évite une écriture à chaque lecture de fichier.

/dev/vg_bdd/lv_mysql  /var/lib/mysql  xfs  defaults,noatime  0 2

Selon la version

Point MariaDB 10.11 MariaDB 11.4 / 11.8 MySQL 8.4 LTS
Nom du binaire serveur mariadbd (mysqld en lien) mariadbd mysqld
Collation par défaut d'utf8mb4 utf8mb4_general_ci uca1400_ai_ci (Debian 13) utf8mb4_0900_ai_ci
Changer innodb_log_file_size à chaud depuis 10.11 à chaud innodb_redo_log_capacity à chaud
Réglages persistants à chaud non (écrire le fichier) non SET PERSIST (mysqld-auto.cnf)
TLS des connexions à configurer activé par défaut depuis 11.4 activé par défaut (certificats générés)

Pièges fréquents

  • Modifier 50-server.cnf : il est remplacé ou provoque une question à chaque mise à jour du paquet. Votre fichier 90-… reste à vous.
  • Un vieux fichier qui gagne : un 99-…cnf ou un zz-…cnf d'un ancien prestataire annule vos réglages. Toujours vérifier la valeur effective.
  • Renommer en .bak dans le mauvais sens : fichier.cnf.bak n'est plus lu (bien), mais fichier.bak.cnf l'est encore.
  • Buffer pool à 90 % de la RAM sur un serveur qui fait aussi tourner PHP ou Java : le noyau tue mariadbd en pleine journée.

Cas réel

Un vendredi soir, la boutique MasterLinux devient très lente. Le serveur a pourtant 16 Go de RAM et l'équipe a « mis le buffer pool à 10 Go » dans 90-production.cnf six mois plus tôt. SELECT @@innodb_buffer_pool_size répond… 256 Mo. Un fichier 99-optimisation-2023.cnf, copié depuis un ancien serveur, était lu en dernier. Tout le jeu de données passait par le disque. Le correctif a pris deux minutes ; la leçon, elle, reste : on vérifie la valeur effective après chaque changement.

Lab

Sur une machine Debian 13 qui imite l'arborescence de MariaDB 11.8, vous allez :

  1. écrire votre fichier de réglages de production ;
  2. découvrir pourquoi le serveur ne les retiendrait pas, et corriger sans rien supprimer ;
  3. ajouter la surcharge systemd ;
  4. régler le swap ;
  5. déclarer le volume dédié aux données dans /etc/fstab.

Les commandes my_print_defaults --mysqld et cnf-effectif <option> vous montrent ce que le serveur lirait.

Quiz

  1. Dans un dossier inclus par !includedir, dans quel ordre les fichiers sont-ils lus, et lesquels ?
  2. Deux fichiers définissent max_connections : lequel gagne ?
  3. Pourquoi innodb_flush_log_at_trx_commit = 1 en production ?
  4. Quelle part de la RAM donner au buffer pool sur un serveur dédié, et pourquoi pas plus ?
  5. Que se passe-t-il si systemd tue MariaDB pendant un arrêt trop long ?
Réponses
  1. Par ordre alphabétique, et seulement les fichiers qui finissent par .cnf.
  2. Celui qui est lu en dernier.
  3. C'est le seul réglage qui écrit le journal redo sur disque à chaque validation : aucune transaction validée n'est perdue en cas de panne.
  4. Environ 60 à 70 % : il faut laisser de la mémoire au système, aux connexions et au cache de fichiers, sinon swap ou OOM killer.
  5. Le serveur redémarre en récupération après panne (crash recovery), plus longue, avec un risque accru ; d'où TimeoutStopSec plus long.

Exercices pratiques

À réaliser sur Debian 13

Faites ce lab sur votre machine

Le terminal, c’est le vôtre : une VM Linux (VirtualBox, VMware, Hyper-V, WSL…) ou Docker/Podman. L’outil ml prépare l’exercice et corrige votre travail ; la leçon se valide toute seule ici.

Créez un compte gratuit pour obtenir votre commande personnelle et faire valider vos labs automatiquement.

Créer mon compte

Tâches à réaliser

  1. Le serveur ml-db-01 (16 Go de RAM, dédié à MariaDB) doit recevoir vos réglages dans un fichier à vous : créez /etc/mysql/mariadb.conf.d/90-production.cnf avec une section [mysqld] contenant innodb_buffer_pool_size = 10G, innodb_log_file_size = 2G, innodb_flush_log_at_trx_commit = 1, max_connections = 300, skip_name_resolve = ON et bind_address = 10.10.20.11.
    Afficher un indiceprintf '%s\n' '[mysqld]' 'innodb_buffer_pool_size = 10G' … > /etc/mysql/mariadb.conf.d/90-production.cnf
    Voir la solution
    printf '%s\n' '[mysqld]' 'innodb_buffer_pool_size = 10G' 'innodb_log_file_size = 2G' 'innodb_flush_log_at_trx_commit = 1' 'max_connections = 300' 'skip_name_resolve = ON' 'bind_address = 10.10.20.11' > /etc/mysql/mariadb.conf.d/90-production.cnf

    Vérification : f=/etc/mysql/mariadb.conf.d/90-production.cnf; grep -qx '\[mysqld\]' $f && grep -Eq '^innodb[_-]buffer[_-]pool[_-]size *= *10G *$' $f && grep -Eq '^innodb[_-]log[_-]file[_-]size *= *2G *$' $f && grep -Eq '^innodb[_-]flush[_-]log[_-]at[_-]trx[_-]commit *= *1 *$' $f && grep -Eq '^max[_-]connections *= *300 *$' $f && grep -Eq '^skip[_-]name[_-]resolve *(= *(ON|1))? *$' $f && grep -Eq '^bind[_-]address *= *10\.10\.20\.11 *$' $f

  2. Vérifiez avec cnf-effectif innodb_buffer_pool_size (ou my_print_defaults --mysqld) : vos valeurs ne sont pas celles que le serveur retiendrait. Trouvez le fichier qui les écrase et neutralisez-le SANS le supprimer (renommez-le pour qu'il ne soit plus lu). Le buffer pool effectif doit être 10G et max_connections 300.
    Afficher un indiceDans un !includedir, les fichiers sont lus par ordre alphabétique et seuls ceux qui finissent par .cnf comptent : 99-… passe après 90-…
    Voir la solution
    mv /etc/mysql/mariadb.conf.d/99-optimisation-2023.cnf /etc/mysql/mariadb.conf.d/99-optimisation-2023.cnf.desactive

    Vérification : test "$(cnf-effectif innodb_buffer_pool_size)" = 10G && test "$(cnf-effectif max_connections)" = 300 && ls /etc/mysql/mariadb.conf.d/ | grep '^99-optimisation-2023' | grep -vq '\.cnf$'

  3. Le service doit pouvoir ouvrir beaucoup de fichiers et avoir le temps de vider un gros buffer pool à l'arrêt : créez la surcharge systemd /etc/systemd/system/mariadb.service.d/limites.conf avec, dans [Service], LimitNOFILE=65535 et TimeoutStopSec=900.
    Afficher un indicemkdir -p /etc/systemd/system/mariadb.service.d puis printf '%s\n' '[Service]' 'LimitNOFILE=65535' 'TimeoutStopSec=900' > …/limites.conf (sur un vrai serveur : systemctl daemon-reload)
    Voir la solution
    mkdir -p /etc/systemd/system/mariadb.service.d && printf '%s\n' '[Service]' 'LimitNOFILE=65535' 'TimeoutStopSec=900' > /etc/systemd/system/mariadb.service.d/limites.conf

    Vérification : f=/etc/systemd/system/mariadb.service.d/limites.conf; grep -qx '\[Service\]' $f && grep -qx 'LimitNOFILE=65535' $f && grep -qx 'TimeoutStopSec=900' $f

  4. Le noyau ne doit envoyer la mémoire du serveur en swap qu'en dernier recours : écrivez /etc/sysctl.d/60-mariadb.conf avec vm.swappiness = 1.
    Afficher un indiceecho 'vm.swappiness = 1' > /etc/sysctl.d/60-mariadb.conf (puis sysctl --system sur un vrai serveur)
    Voir la solution
    echo 'vm.swappiness = 1' > /etc/sysctl.d/60-mariadb.conf

    Vérification : grep -Eq '^vm\.swappiness *= *1 *$' /etc/sysctl.d/60-mariadb.conf

  5. Les données doivent vivre sur leur propre volume : ajoutez à /etc/fstab (sans toucher aux autres lignes) le montage du volume /dev/vg_bdd/lv_mysql sur /var/lib/mysql, en xfs, avec l'option noatime, contrôle fsck 0 2.
    Afficher un indiceecho '/dev/vg_bdd/lv_mysql /var/lib/mysql xfs defaults,noatime 0 2' >> /etc/fstab (deux chevrons : on ajoute)
    Voir la solution
    echo '/dev/vg_bdd/lv_mysql /var/lib/mysql xfs defaults,noatime 0 2' >> /etc/fstab

    Vérification : awk '$1=="/dev/vg_bdd/lv_mysql" && $2=="/var/lib/mysql" && $3=="xfs" && $4 ~ /noatime/ && $6=="2" {ok=1} END {exit !ok}' /etc/fstab && grep -q '/boot' /etc/fstab && grep -q 'lv_swap' /etc/fstab