---
title: MySQL / MariaDB
source: https://synapx.fr/blog/mysql-mariadb/
date: 2026-06-26
category: Bases de données
site: SynapxLab
---

# MySQL / MariaDB

## Installer MariaDB

```bash
apt install mariadb-server -y
mysql_secure_installation
```

## Configuration de MariaDB

Modifiez le fichier de configuration de MariaDB (`my.cnf` ou `mariadb.cnf`). Sur la plupart des systèmes, il se trouve dans `/etc/mysql/` ou `/etc/mariadb/`.

```bash
cd /etc/mysql/
# ou, selon la distribution :
# cd /etc/mariadb/
nano /etc/mysql/mariadb.cnf
```

Ces valeurs sont également consultables dans phpMyAdmin, via Accueil / Variables et paramètres du serveur.

```ini
[mysqld]
#port = 3306
#bind-address = 127.0.0.1
#datadir = /var/lib/mysql
#socket = /var/run/mysqld/mysqld.sock
#log_error = /var/log/mysql/error.log
#pid-file = /var/run/mysqld/mysqld.pid
#
#max_connections = 100
#query_cache_size = 16M
#query_cache_type = 1
#innodb_buffer_pool_size = 256M
#innodb_log_file_size = 64M
#innodb_flush_log_at_trx_commit = 1
#
#skip-networking      # Désactive les connexions réseau, n'autorisant que les connexions locales via le socket Unix.
#skip-name-resolve    # Désactive la résolution de nom d'hôte pour améliorer les performances.
#
#log_bin = /var/log/mysql/mysql-bin.log
#server_id = 1          # Identifiant unique du serveur pour la réplication.
#binlog_format = MIXED  # (ROW, STATEMENT, MIXED)
#relay_log = /var/log/mysql/mysql-relay-bin.log
#
#default_storage_engine = InnoDB
#character_set_server = utf8mb4
#collation_server = utf8mb4_general_ci
```

```bash
systemctl restart mariadb
systemctl status mariadb

# Désinstallation complète
systemctl stop mariadb
apt-get remove --purge mariadb-server mariadb-client mariadb-common
apt-get autoremove
apt-get autoclean
rm -rf /etc/mysql /var/lib/mysql
deluser mysql
delgroup mysql
```

## Se connecter et explorer les bases

```bash
mysql -u root -p                          # Ouvrir le client (le mot de passe est demandé)
mariadb -u root -p                        # Client MariaDB, équivalent sur les versions récentes
mysql -u app -p -h 127.0.0.1 ma_base      # Connexion réseau directement sur une base
```

```sql
SHOW DATABASES;                           -- Lister les bases
USE ma_base;                              -- Sélectionner la base courante
SHOW TABLES;                              -- Lister les tables de la base courante
DESCRIBE clients;                         -- Colonnes et types d'une table
SHOW CREATE TABLE clients\G               -- Instruction de création complète (\G = affichage vertical)
SELECT VERSION();                         -- Version du serveur
STATUS;                                   -- Informations de connexion et du serveur
EXIT;                                     -- Quitter le client (ou \q)
```

## Commandes SQL de base

```sql
-- Créer une base et une table
CREATE DATABASE boutique CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE boutique;

CREATE TABLE clients (
  id       INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  nom      VARCHAR(100) NOT NULL,
  email    VARCHAR(150) NOT NULL UNIQUE,
  cree_le  DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- Insérer des données
INSERT INTO clients (nom, email) VALUES ('Ada Lovelace', 'ada@exemple.fr');
INSERT INTO clients (nom, email) VALUES
  ('Grace Hopper', 'grace@exemple.fr'),
  ('Alan Turing',  'alan@exemple.fr');

-- Lire (SELECT)
SELECT * FROM clients;
SELECT nom, email FROM clients WHERE nom LIKE 'A%' ORDER BY nom ASC LIMIT 10;
SELECT COUNT(*) FROM clients;

-- Jointure entre deux tables
SELECT c.nom, co.total
FROM clients c
JOIN commandes co ON co.client_id = c.id
WHERE co.total > 100;

-- Mettre à jour et supprimer (ne jamais oublier le WHERE)
UPDATE clients SET email = 'ada.l@exemple.fr' WHERE id = 1;
DELETE FROM clients WHERE id = 3;

-- Faire évoluer la structure et indexer
ALTER TABLE clients ADD COLUMN ville VARCHAR(80);
CREATE INDEX idx_clients_nom ON clients (nom);

-- Supprimer une table ou une base
DROP TABLE commandes;
DROP DATABASE boutique;
```

## Gérer les utilisateurs et les privilèges

```sql
-- Créer un utilisateur : local (socket) puis réseau
CREATE USER 'app'@'localhost' IDENTIFIED BY 'MotDePasseFort';
CREATE USER 'app'@'%'         IDENTIFIED BY 'MotDePasseFort';   -- depuis n'importe quel hôte

-- Accorder des privilèges CIBLÉS sur une seule base (principe du moindre privilège)
GRANT SELECT, INSERT, UPDATE, DELETE ON boutique.* TO 'app'@'localhost';

-- Inspecter, retirer, supprimer
SHOW GRANTS FOR 'app'@'localhost';
REVOKE INSERT, UPDATE, DELETE ON boutique.* FROM 'app'@'localhost';
DROP USER 'app'@'localhost';

-- Changer un mot de passe
ALTER USER 'app'@'localhost' IDENTIFIED BY 'NouveauMotDePasse';

FLUSH PRIVILEGES;                         -- Recharger la table des privilèges
```

> Accordez toujours le minimum nécessaire : une application web se contente en général de `SELECT, INSERT, UPDATE, DELETE` sur *sa* base, sans `ALL PRIVILEGES` ni `GRANT OPTION`, réservés à l'administration.

## Sauvegarde et restauration

La sauvegarde logique repose sur `mysqldump`, qui exporte la structure et les données sous forme d'instructions SQL. La restauration réinjecte ce fichier avec le client `mysql` (ou `mariadb`).

### Sauvegarder une base

```bash
# Une base précise
mysqldump -u root -p ma_base > ma_base.sql

# Compressée à la volée (recommandé) → fichier .sql.gz
mysqldump -u root -p ma_base | gzip > ma_base_$(date +%F).sql.gz

# Toutes les bases du serveur
mysqldump -u root -p --all-databases | gzip > full_$(date +%F).sql.gz

# Seulement la structure (sans les données)
mysqldump -u root -p --no-data ma_base > ma_base_schema.sql

# Seulement les données (sans le schéma)
mysqldump -u root -p --no-create-info ma_base > ma_base_data.sql

# Plusieurs bases nommées
mysqldump -u root -p --databases base1 base2 | gzip > bases_$(date +%F).sql.gz
```

Quelques options utiles pour une sauvegarde cohérente, en particulier sur des tables InnoDB :

```bash
mysqldump -u root -p \
  --single-transaction \  # dump cohérent sans verrouiller les tables (InnoDB)
  --quick \               # lit ligne par ligne, ménage la mémoire sur les grosses tables
  --routines \            # inclut les procédures stockées et fonctions
  --triggers \            # inclut les déclencheurs
  --events \              # inclut les événements planifiés
  ma_base | gzip > ma_base_$(date +%F).sql.gz
```

### Sélectionner ou exclure des tables

On peut ne sauvegarder que certaines tables, ou au contraire en écarter. Les tables à inclure se listent après le nom de la base ; les tables à exclure passent par `--ignore-table`, à répéter et à préfixer par le nom de la base.

```bash
# Seulement certaines tables (les noms suivent la base)
mysqldump -u root -p ma_base clients commandes > ma_base_partiel.sql

# Toute la base SAUF certaines tables (--ignore-table à répéter, préfixé par la base)
mysqldump -u root -p ma_base \
  --ignore-table=ma_base.logs \
  --ignore-table=ma_base.sessions \
  | gzip > ma_base_sans_logs_$(date +%F).sql.gz

# Exclure les données volumineuses mais garder leur structure :
# 1) tout sauvegarder en excluant les données des tables lourdes
mysqldump -u root -p ma_base --ignore-table=ma_base.logs | gzip > ma_base_$(date +%F).sql.gz
# 2) ajouter uniquement le schéma des tables exclues
mysqldump -u root -p --no-data ma_base logs | gzip >> ma_base_$(date +%F).sql.gz
```

Pour exclure une même table sur toutes les bases lors d'un `--all-databases`, chaque `--ignore-table` doit malgré tout nommer la base concernée : il n'existe pas de motif générique, on répète l'option pour chaque couple `base.table`.

### Restaurer une base

```bash
# La base cible doit exister au préalable
mysql -u root -p -e "CREATE DATABASE ma_base CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"

# Depuis un fichier .sql
mysql -u root -p ma_base < ma_base.sql

# Depuis un fichier compressé .sql.gz (sans le décompresser)
gunzip < ma_base_2026-07-05.sql.gz | mysql -u root -p ma_base
# variante équivalente :
zcat ma_base_2026-07-05.sql.gz | mysql -u root -p ma_base
```

Un dump créé avec `--all-databases` ou `--databases` contient déjà les instructions `CREATE DATABASE` / `USE` : on le restaure alors sans préciser de base.

```bash
zcat full_2026-07-05.sql.gz | mysql -u root -p
```

Avec le client `mariadb` et un utilisateur applicatif, le mot de passe peut être passé directement à la suite de `-p` (sans espace). Le dump `--databases` portant déjà le `CREATE DATABASE` / `USE`, aucune base n'est précisée :

```bash
# Restaurer : décompresser et réinjecter dans MariaDB
gunzip < /var/bases.sql.gz | mariadb -u user -p'password'

#  sauvegarder et compresser
mariadb-dump -u user -p'password' --databases bases | gzip > bases.sql.gz
```

> Passer le mot de passe dans la commande l'expose dans l'historique du shell et la liste des processus (`ps`). Pour un usage régulier, préférez `~/.my.cnf` (chmod 600) décrit plus bas, ou l'invite interactive avec `-p` seul. Sur MariaDB récent, `mariadb`/`mariadb-dump` remplacent `mysql`/`mysqldump`, qui restent disponibles comme alias.

### Variante ZIP (.sql.zip)

Contrairement à `gzip`, `zip` produit une **archive** (elle peut contenir plusieurs fichiers) et non un simple flux compressé : on ne peut donc pas l'enchaîner par un pipe aussi directement. Il faut d'abord installer les outils :

```bash
apt install zip unzip -y
```

```bash
# Sauvegarder : dump vers un .sql, puis archivage en .sql.zip
mysqldump -u root -p --databases ma_base > ma_base.sql
zip ma_base.sql.zip ma_base.sql   # crée l'archive
rm ma_base.sql                    # on ne garde que le .zip

# Variante en une ligne, sans fichier intermédiaire :
# le contenu est envoyé sur l'entrée standard de zip (l'entrée s'appelle alors « - »)
mysqldump -u root -p --databases ma_base | zip ma_base.sql.zip -
```

```bash
# Restaurer : extraire le contenu de l'archive vers l'entrée de MariaDB
# -p écrit le fichier extrait sur la sortie standard (peu importe son nom dans l'archive)
unzip -p ma_base.sql.zip | mariadb -u synapxlab -p'xxxxxxxxxxxxxxxxx'
```

Un dump `--databases` embarquant déjà `CREATE DATABASE` / `USE`, aucune base n'est précisée à la restauration. À taille de données égale, `zip` compresse un peu moins bien que `gzip` sur un dump SQL ; on le choisit surtout pour la compatibilité (archive ouvrable sous Windows d'un double-clic).

### Automatiser avec cron

```bash
crontab -e
```

```cron
# Sauvegarde quotidienne à 2 h, conservée 7 jours
0 2 * * * mysqldump -u root -p'MOT_DE_PASSE' --single-transaction --routines ma_base | gzip > /var/backups/mysql/ma_base_$(date +\%F).sql.gz
30 2 * * * find /var/backups/mysql -name '*.sql.gz' -mtime +7 -delete
```

Pour éviter d'exposer le mot de passe dans la ligne de commande ou la crontab, on le place dans un fichier protégé `~/.my.cnf` :

```ini
# ~/.my.cnf  (chmod 600)
[client]
user = root
password = MOT_DE_PASSE
```

`mysqldump` et `mysql` liront alors ces identifiants automatiquement, sans option `-u` ni `-p`.

## Maintenance, diagnostic et optimisation

```sql
SHOW PROCESSLIST;                         -- Requêtes en cours d'exécution
SHOW STATUS LIKE 'Threads_connected';     -- Connexions actives
SHOW VARIABLES LIKE 'max_connections';    -- Valeur d'un paramètre du serveur
EXPLAIN SELECT * FROM clients WHERE nom = 'Ada Lovelace';  -- Plan d'exécution (l'index est-il utilisé ?)
ANALYZE TABLE clients;                    -- Met à jour les statistiques d'index
OPTIMIZE TABLE clients;                   -- Défragmente et réordonne la table
CHECK TABLE clients;                      -- Vérifie l'intégrité
REPAIR TABLE clients;                     -- Répare (surtout utile en MyISAM)
```

```bash
# Vérifier et réparer toutes les tables depuis le shell
mysqlcheck -u root -p --all-databases --check
mysqlcheck -u root -p --all-databases --auto-repair --optimize
```

Si le mot de passe root est perdu, on redémarre MariaDB en mode sans privilèges pour le réinitialiser :

```bash
sudo systemctl stop mariadb
sudo mysqld_safe --skip-grant-tables --skip-networking &
mysql -u root
```

```sql
-- Une fois connecté sans mot de passe :
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'NouveauMotDePasseRoot';
```

```bash
# Puis on arrête le mode dégradé et on relance normalement
sudo kill "$(pgrep mysqld)"
sudo systemctl start mariadb
```

## phpMyAdmin

Accès via `http://votre_ip/phpmyadmin`.

```bash
apt install phpmyadmin -y

apt install pwgen      # générateur de mots de passe en ligne de commande
pwgen -syB 24 1
# -s → mode sécurisé (cryptographique)
# -y → inclure des caractères spéciaux
# -B → pas de caractères ambigus (0, O, l, 1...)
```

À la question « Faut-il configurer la base de données de phpMyAdmin avec dbconfig-common ? », répondre non permet de conserver la maîtrise de la configuration sans créer d'utilisateurs ou de bases superflus.

```sql
-- Accès : http://IP/phpmyadmin/
-- mysql -u root -p

CREATE USER 'admin'@'localhost' IDENTIFIED BY '+@%Xw7YVd5.ceO7uvJ_]';
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
```

### Générer une clef blowfish_secret pour phpMyAdmin

`blowfish_secret` sert à sécuriser les cookies ; cette clef est indispensable au bon fonctionnement de phpMyAdmin en mode sécurisé. Elle doit comporter au minimum 32 caractères et être aléatoire.

```bash
blowfish=$(pwgen -syB 32 1)
echo "\$cfg['blowfish_secret'] = '$blowfish';"
# ou avec nano :
nano /var/lib/phpmyadmin/blowfish_secret.inc.php
```

### Thèmes alternatifs pour phpMyAdmin (mode sombre)

Quelques dépôts de thèmes sombres :

- https://github.com/pma-theme/metronome-dark
- https://github.com/evilpie/phpmyadmin-dark-theme
- https://github.com/PMA-Theme-Generator/themes

```bash
cd /usr/share/phpmyadmin/themes/
apt install git -y
git clone https://github.com/evilpie/phpmyadmin-dark-theme.git darkmode
systemctl reload apache2
nano /etc/phpmyadmin/config.inc.php
```

```php
$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['user'] = 'phpmyadmin';
$cfg['Servers'][$i]['password'] = 'your_password';

$cfg['UploadDir'] = '';
$cfg['MaxFileSize'] = 16777216; // 16 MB en octets
$cfg['ExecTimeLimit'] = 300;    // 5 minutes
```

### Privilèges et gestion des bases

```sql
-- mariadb
GRANT ALL PRIVILEGES ON *.* TO 'phpmyadmin'@'localhost' WITH GRANT OPTION;
SHOW GRANTS FOR 'phpmyadmin'@'localhost';
ALTER USER 'phpmyadmin'@'localhost' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON *.* TO 'phpmyadmin'@'localhost' WITH GRANT OPTION;
CREATE USER 'doc_user'@'localhost' IDENTIFIED BY 'doc_password';
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'doc_user'@'localhost';
FLUSH PRIVILEGES;
CREATE DATABASE testdb;
```

```bash
systemctl restart mariadb
systemctl restart apache2
mariadb -u phpmyadmin -p
```

### Désinstaller phpMyAdmin

```bash
apt-get remove --purge phpmyadmin
apt-get autoremove
apt-get autoclean
rm -rf /usr/share/phpmyadmin /var/lib/phpmyadmin /etc/phpmyadmin
systemctl restart apache2
```
