Les bases de MariaDB/MySQL pour les administrateurs

Credit : Logo officiel

Les bases de MariaDB/MySQL pour les administrateurs

Dylan D. — Agent Support Technique Serveur Linux 2223 mots 12 min de lecture

phpMyAdmin est down, le client appelle, vous savez quoi faire ?

Un collegue admin systeme m'a appele un dimanche soir l'an dernier. Son phpMyAdmin venait de planter (un certif SSL expire qui a casse Apache, classique), et il devait restaurer une base de donnees pour qu'un client e-commerce ouvre lundi matin. Il connaissait WordPress par coeur mais n'avait jamais vraiment tape de commandes SQL en direct. Resultat : panique, ticket support, deux heures perdues. Avec trois lignes de mysqldump il s'en serait sorti en cinq minutes.

Depuis je leur dis tous : si vous gerez des serveurs Linux, vous devez savoir parler a MariaDB sans interface graphique. Ce guide rassemble les commandes que j'utilise vraiment au quotidien, celles que vous allez taper deux fois par semaine si vous administrez des sites WordPress, PrestaShop ou des applis maison.

MariaDB et MySQL sont compatibles a 95% pour ce qui est du langage SQL et des outils en ligne de commande. Sur Debian 12 et Ubuntu 24.04, c'est MariaDB 10.11 ou 11.x qui est installe par defaut. Sur les VPS IONOS, vous tombez en general sur la meme version. Tout ce qui suit fonctionne sur les deux moteurs.

Se connecter au serveur

La commande de base, celle que vous taperez 50 fois par jour :

# Se connecter en root
sudo mysql

# Ou avec le mot de passe explicitement
mysql -u root -p

# Se connecter a une base specifique
mysql -u utilisateur -p nom_base

# Se connecter sur un serveur distant
mysql -h db.monsite.fr -P 3306 -u utilisateur -p

# Executer une requete one-shot sans entrer dans le shell
mysql -u root -p -e "SHOW DATABASES;"

Sur Debian/Ubuntu, depuis MariaDB 10.4, le user root est configure par defaut en authentification unix_socket. Ca veut dire que sudo mysql marche sans mot de passe, mais mysql -u root -p echoue. C'est un piege classique pour les nouveaux. Si vous voulez vous connecter en root avec un mot de passe (par exemple depuis un script), il faut creer un user separe.

Le fichier .my.cnf pour eviter de retaper le mot de passe

Dans votre home directory, creez ~/.my.cnf :

[client]
user=root
password=VotreMotDePasseRoot

Puis :

chmod 600 ~/.my.cnf

Maintenant un simple mysql vous connecte sans demander de mot de passe. Pratique pour les scripts de backup. Le chmod 600 est obligatoire, sinon n'importe quel user du systeme peut lire le fichier et donc votre mot de passe.

Gerer les bases de donnees

Creer, lister, supprimer. Les operations de base.

-- Creer une base avec le bon charset
CREATE DATABASE monsite CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- Lister les bases
SHOW DATABASES;

-- Selectionner une base
USE monsite;

-- Voir la base courante
SELECT DATABASE();

-- Supprimer (irreversible, attention)
DROP DATABASE test_ancien;

Le charset utf8mb4 est OBLIGATOIRE en 2026. Le vieux utf8 de MySQL est en realite un utf8 sur 3 octets qui ne supporte pas les emojis ni certains caracteres asiatiques. utf8mb4 c'est le vrai utf8, sur 4 octets. Si vous creez une base en 2026 avec autre chose qu'utf8mb4, vous allez vous retrouver avec des ??? partout des qu'un utilisateur tape un emoji.

La collation utf8mb4_unicode_ci gere correctement le tri et la comparaison case-insensitive. Pour WordPress, prenez plutot utf8mb4_unicode_520_ci qui est plus moderne. Pour les nouvelles installations MariaDB 10.5+, utf8mb4_uca1400_ai_ci est la valeur par defaut et ca fonctionne tres bien.

Voir l'espace utilise par chaque base

SELECT 
    table_schema AS "Base",
    ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS "Taille (MB)"
FROM information_schema.tables
GROUP BY table_schema
ORDER BY SUM(data_length + index_length) DESC;

Utile pour savoir laquelle de vos bases bouffe l'espace disque. J'ai eu un cas ou une table de logs WordPress faisait 14 Go a elle toute seule.

Creer et modifier des tables

CREATE TABLE articles (
    id INT AUTO_INCREMENT PRIMARY KEY,
    titre VARCHAR(255) NOT NULL,
    slug VARCHAR(255) NOT NULL UNIQUE,
    contenu LONGTEXT,
    auteur_id INT,
    categorie_id INT,
    date_creation DATETIME DEFAULT CURRENT_TIMESTAMP,
    date_modif DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    publie BOOLEAN DEFAULT FALSE,
    INDEX idx_auteur (auteur_id),
    INDEX idx_date (date_creation),
    INDEX idx_publie_date (publie, date_creation),
    FOREIGN KEY (auteur_id) REFERENCES utilisateurs(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Voir la structure
DESCRIBE articles;
SHOW CREATE TABLE articles;

-- Lister toutes les tables
SHOW TABLES;

-- Ajouter une colonne
ALTER TABLE articles ADD COLUMN vues INT DEFAULT 0 AFTER publie;

-- Renommer une colonne (MariaDB 10.5+)
ALTER TABLE articles RENAME COLUMN vues TO nb_vues;

-- Supprimer une colonne
ALTER TABLE articles DROP COLUMN nb_vues;

-- Ajouter un index
ALTER TABLE articles ADD INDEX idx_slug (slug);

Le moteur InnoDB est obligatoire pour les nouvelles tables. MyISAM c'est mort, il ne supporte pas les transactions ni les cles etrangeres. Si vous heritez d'une base ancienne avec des tables MyISAM, convertissez-les :

ALTER TABLE ma_table ENGINE=InnoDB;

Index composites, le secret des performances

L'index idx_publie_date (publie, date_creation) dans l'exemple n'est pas la pour faire joli. Quand vous faites WHERE publie = TRUE ORDER BY date_creation DESC (la requete typique pour afficher la home d'un blog), MariaDB peut utiliser cet index composite pour eviter un scan complet de la table. La regle : mettez d'abord les colonnes filtrees par egalite, puis celles utilisees pour le tri.

Requetes SELECT essentielles

-- Recuperer les 20 derniers articles publies avec leur auteur
SELECT a.id, a.titre, u.nom, a.date_creation
FROM articles a
JOIN utilisateurs u ON a.auteur_id = u.id
WHERE a.publie = TRUE
ORDER BY a.date_creation DESC
LIMIT 20;

-- Compter par categorie avec filtre
SELECT categorie_id, COUNT(*) AS total
FROM articles
WHERE publie = TRUE
GROUP BY categorie_id
HAVING total > 5
ORDER BY total DESC;

-- Recherche LIKE (attention aux performances sur grosses tables)
SELECT * FROM articles WHERE titre LIKE '%linux%' LIMIT 10;

-- Recherche fulltext (beaucoup plus rapide)
ALTER TABLE articles ADD FULLTEXT INDEX ft_titre_contenu (titre, contenu);
SELECT * FROM articles 
WHERE MATCH(titre, contenu) AGAINST('linux serveur' IN NATURAL LANGUAGE MODE);

-- Update conditionnel
UPDATE articles SET publie = FALSE WHERE date_creation < '2020-01-01';

-- Delete avec confirmation par count d'abord
SELECT COUNT(*) FROM articles WHERE publie = FALSE AND date_creation < '2020-01-01';
DELETE FROM articles WHERE publie = FALSE AND date_creation < '2020-01-01';

Regle absolue avec DELETE et UPDATE sans WHERE limitant : faites toujours un SELECT avec le meme WHERE avant. J'ai deja vu un collegue executer DELETE FROM users parce qu'il avait oublie le WHERE. 50 000 utilisateurs partis en fumee, restauration depuis le backup de la veille, deux heures de stress et un client tres en colere.

Gestion des utilisateurs et privileges

-- Creer un utilisateur (MariaDB/MySQL 8+)
CREATE USER 'webapp'@'localhost' IDENTIFIED BY 'MotDePasse_Solide2026!';

-- Pour autoriser une IP specifique
CREATE USER 'webapp'@'10.0.0.5' IDENTIFIED BY 'MotDePasse_Solide2026!';

-- Pour un user accessible depuis n'importe ou (a eviter)
CREATE USER 'webapp'@'%' IDENTIFIED BY 'MotDePasse_Solide2026!';

-- Donner des privileges sur une base
GRANT SELECT, INSERT, UPDATE, DELETE ON monsite.* TO 'webapp'@'localhost';

-- Donner tous les privileges (a eviter sauf cas precis)
GRANT ALL PRIVILEGES ON monsite.* TO 'webapp'@'localhost';

-- Toujours flush apres modification
FLUSH PRIVILEGES;

-- Voir les privileges
SHOW GRANTS FOR 'webapp'@'localhost';

-- Changer un mot de passe
ALTER USER 'webapp'@'localhost' IDENTIFIED BY 'NouveauMotDePasseSolide2026!';

-- Revoquer un privilege
REVOKE DELETE ON monsite.* FROM 'webapp'@'localhost';

-- Supprimer un user
DROP USER 'webapp'@'localhost';

Regle d'or : ne JAMAIS utiliser root pour vos applications. Creez un user dedie par application avec le minimum de privileges necessaires. Pour WordPress, par exemple, SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, INDEX sur sa base suffisent. Pas besoin de privileges globaux ni de FILE/PROCESS/SUPER.

Auditer les comptes existants

-- Lister tous les utilisateurs
SELECT User, Host FROM mysql.user;

-- Voir les utilisateurs avec privileges globaux dangereux
SELECT User, Host FROM mysql.user 
WHERE Super_priv='Y' OR File_priv='Y' OR Process_priv='Y';

-- Comptes sans mot de passe (a virer immediatement)
SELECT User, Host FROM mysql.user WHERE authentication_string = '';

Quand je reprends la gestion d'un serveur, c'est toujours la premiere chose que je verifie. Vous seriez surpris du nombre de bases en prod avec un user test sans mot de passe qui traine.

Sauvegardes avec mysqldump

Les backups, c'est la base. Si vous ne faites pas de backup, ne lisez meme pas le reste, allez tout de suite mettre en place un dump cron.

# Sauvegarder une base
mysqldump -u root monsite > /var/backups/monsite_$(date +%Y%m%d).sql

# Sauvegarder toutes les bases
mysqldump -u root --all-databases > /var/backups/all_$(date +%Y%m%d).sql

# Avec compression (indispensable pour les grosses bases)
mysqldump -u root monsite | gzip > /var/backups/monsite_$(date +%Y%m%d).sql.gz

# Avec routines, triggers et events (recommande)
mysqldump -u root --routines --triggers --events --single-transaction monsite | gzip > /var/backups/monsite_$(date +%Y%m%d).sql.gz

# Backup de structure uniquement (pas de donnees)
mysqldump -u root --no-data monsite > monsite_schema.sql

# Backup de donnees uniquement (pas de structure)
mysqldump -u root --no-create-info monsite > monsite_data.sql

L'option --single-transaction est cruciale pour les bases InnoDB. Elle prend un snapshot coherent sans verrouiller les tables, donc votre site continue a fonctionner pendant le backup.

Restauration

# Restaurer un dump SQL
mysql -u root monsite < monsite_20260507.sql

# Restaurer depuis un fichier compresse
gunzip < monsite_20260507.sql.gz | mysql -u root monsite

# Restaurer toutes les bases (pour migration de serveur)
mysql -u root < all_20260507.sql

Script de backup automatise

Voici le script que je colle dans /usr/local/bin/mysql-backup.sh sur tous mes serveurs :

#!/bin/bash
BACKUP_DIR="/var/backups/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=14

mkdir -p $BACKUP_DIR

for DB in $(mysql -e "SHOW DATABASES;" | grep -Ev "(Database|information_schema|performance_schema|sys|mysql)"); do
    mysqldump --routines --triggers --events --single-transaction "$DB" | gzip > "$BACKUP_DIR/${DB}_${DATE}.sql.gz"
done

# Nettoyage des backups anciens
find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete

Dans le crontab :

0 3 * * * /usr/local/bin/mysql-backup.sh >> /var/log/mysql-backup.log 2>&1

Un dump compresse a 3h du mat, 14 jours de retention, log dans un fichier. Simple et efficace. Ca m'a sauve la mise au moins cinq fois sur des migrations qui avaient mal tourne.

Optimiser les performances

Quand un site rame, c'est tres souvent la base. Voici les commandes pour diagnostiquer :

-- Activer le slow query log (requetes > 1 seconde)
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';

-- Voir les processus en cours
SHOW PROCESSLIST;

-- Voir les requetes en cours avec details
SHOW FULL PROCESSLIST;

-- Tuer une requete bloquee
KILL 12345;  -- 12345 = ID de la requete dans PROCESSLIST

-- Statut du serveur
SHOW GLOBAL STATUS LIKE 'Threads%';
SHOW GLOBAL STATUS LIKE 'Connections';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool%';

Parametres cles dans /etc/mysql/mariadb.conf.d/50-server.cnf :

[mysqld]
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
max_connections = 150
query_cache_type = 0
tmp_table_size = 64M
max_heap_table_size = 64M
slow_query_log = 1
long_query_time = 1

Regle pour innodb_buffer_pool_size : 50 a 70% de la RAM totale si le serveur est dedie a MySQL. Sur un VPS partage avec PHP-FPM et Nginx, soyez plus conservateur, 30 a 40%. Sur une machine 4 Go, 1,5 Go pour InnoDB c'est bien.

innodb_flush_log_at_trx_commit = 2 ameliore les perfs au prix d'un risque tres limite (perte des transactions de la derniere seconde en cas de crash). Pour la plupart des sites web, c'est un excellent compromis.

Erreurs courantes et leur fix

ERROR 1045 (28000): Access denied for user. Le mot de passe est faux, ou le user n'existe pas pour ce host. Verifiez avec SELECT User, Host FROM mysql.user; que le user existe pour le bon host (localhost, %, ou IP specifique). Le user webapp@% ne peut PAS se connecter via webapp@localhost parce que MariaDB matche le host le plus specifique.

ERROR 1146 (42S02): Table doesn't exist. La table existe mais le nom est sensible a la casse sous Linux. Verifiez SHOW TABLES; et matchez exactement la casse. Sous Linux les noms de table sont sensibles a la casse, sous Windows non, c'est une source classique de bugs en migration.

Got error 28 from storage engine. Disque plein. df -h pour confirmer, puis libe rez de l'espace ou agrandissez la partition.

ERROR 1064 (42000): You have an error in your SQL syntax. Erreur de syntaxe. Le message indique a quel endroit MariaDB a bloque. 90% du temps c'est un mot reserve utilise comme nom de colonne (order, desc, key, group) qu'il faut entourer de backticks : `order`.

Too many connections. Vous avez atteint max_connections. Soit vraiment trop de trafic, soit (plus souvent) une appli qui ne ferme pas ses connexions. SHOW PROCESSLIST; pour voir si elles sont en Sleep depuis longtemps. En urgence, SET GLOBAL max_connections = 300; pour respirer, puis investiguer.

Pour aller plus loin

Conclusion : la console SQL, le couteau suisse de l'admin

phpMyAdmin c'est confortable, mais le jour ou il vous lache, vous etes content de savoir taper un mysqldump ou un SHOW PROCESSLIST directement. Toutes les commandes ci-dessus, je les utilise vraiment au quotidien sur les VPS que je gere. Mettez-les en favoris, copiez-les dans votre fichier de notes admin, ou imprimez la fiche et collez-la a cote de votre ecran. Et surtout, faites des backups automatises. Serieusement, faites des backups.

# Articles similaires

Sur les memes sujets et plus loin